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> 9964Sigor@sysoev.ru 10964Sigor@sysoev.ru 11964Sigor@sysoev.ru typedef enum { 121059Sigor@sysoev.ru NXT_HTTP_ROUTE_TABLE = 0, 131059Sigor@sysoev.ru NXT_HTTP_ROUTE_STRING, 14964Sigor@sysoev.ru NXT_HTTP_ROUTE_STRING_PTR, 15964Sigor@sysoev.ru NXT_HTTP_ROUTE_HEADER, 16964Sigor@sysoev.ru NXT_HTTP_ROUTE_ARGUMENT, 17964Sigor@sysoev.ru NXT_HTTP_ROUTE_COOKIE, 181110Saxel.duch@nginx.com NXT_HTTP_ROUTE_SCHEME, 19964Sigor@sysoev.ru } nxt_http_route_object_t; 20964Sigor@sysoev.ru 21964Sigor@sysoev.ru 22964Sigor@sysoev.ru typedef enum { 23964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_EXACT = 0, 24964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_BEGIN, 251032Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_MIDDLE, 26964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_END, 27964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_SUBSTRING, 28964Sigor@sysoev.ru } nxt_http_route_pattern_type_t; 29964Sigor@sysoev.ru 30964Sigor@sysoev.ru 31964Sigor@sysoev.ru typedef enum { 32964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_NOCASE = 0, 33964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_LOWCASE, 34964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_UPCASE, 35964Sigor@sysoev.ru } nxt_http_route_pattern_case_t; 36964Sigor@sysoev.ru 37964Sigor@sysoev.ru 38964Sigor@sysoev.ru typedef struct { 391264Sigor@sysoev.ru nxt_conf_value_t *pass; 401264Sigor@sysoev.ru nxt_conf_value_t *share; 41*1270Sigor@sysoev.ru nxt_conf_value_t *proxy; 421264Sigor@sysoev.ru } nxt_http_route_action_conf_t; 431264Sigor@sysoev.ru 441264Sigor@sysoev.ru 451264Sigor@sysoev.ru typedef struct { 46964Sigor@sysoev.ru nxt_conf_value_t *host; 47964Sigor@sysoev.ru nxt_conf_value_t *uri; 48964Sigor@sysoev.ru nxt_conf_value_t *method; 491059Sigor@sysoev.ru nxt_conf_value_t *headers; 501061Sigor@sysoev.ru nxt_conf_value_t *arguments; 511062Sigor@sysoev.ru nxt_conf_value_t *cookies; 521110Saxel.duch@nginx.com nxt_conf_value_t *scheme; 53964Sigor@sysoev.ru } nxt_http_route_match_conf_t; 54964Sigor@sysoev.ru 55964Sigor@sysoev.ru 56964Sigor@sysoev.ru typedef struct { 571032Sigor@sysoev.ru u_char *start1; 581032Sigor@sysoev.ru u_char *start2; 591032Sigor@sysoev.ru uint32_t length1; 601032Sigor@sysoev.ru uint32_t length2; 61964Sigor@sysoev.ru uint32_t min_length; 62964Sigor@sysoev.ru 63964Sigor@sysoev.ru nxt_http_route_pattern_type_t type:8; 64964Sigor@sysoev.ru uint8_t case_sensitive; /* 1 bit */ 65964Sigor@sysoev.ru uint8_t negative; /* 1 bit */ 66964Sigor@sysoev.ru uint8_t any; /* 1 bit */ 67964Sigor@sysoev.ru } nxt_http_route_pattern_t; 68964Sigor@sysoev.ru 69964Sigor@sysoev.ru 70964Sigor@sysoev.ru typedef struct { 711061Sigor@sysoev.ru uint16_t hash; 721061Sigor@sysoev.ru uint16_t name_length; 731061Sigor@sysoev.ru uint32_t value_length; 741061Sigor@sysoev.ru u_char *name; 751061Sigor@sysoev.ru u_char *value; 761061Sigor@sysoev.ru } nxt_http_name_value_t; 771061Sigor@sysoev.ru 781061Sigor@sysoev.ru 791061Sigor@sysoev.ru typedef struct { 801062Sigor@sysoev.ru uint16_t hash; 811062Sigor@sysoev.ru uint16_t name_length; 821062Sigor@sysoev.ru uint32_t value_length; 831062Sigor@sysoev.ru u_char *name; 841062Sigor@sysoev.ru u_char *value; 851062Sigor@sysoev.ru } nxt_http_cookie_t; 861062Sigor@sysoev.ru 871062Sigor@sysoev.ru 881062Sigor@sysoev.ru typedef struct { 891059Sigor@sysoev.ru /* The object must be the first field. */ 901059Sigor@sysoev.ru nxt_http_route_object_t object:8; 91964Sigor@sysoev.ru uint32_t items; 921059Sigor@sysoev.ru 931059Sigor@sysoev.ru union { 941059Sigor@sysoev.ru uintptr_t offset; 951059Sigor@sysoev.ru 961059Sigor@sysoev.ru struct { 971059Sigor@sysoev.ru u_char *start; 981059Sigor@sysoev.ru uint16_t hash; 991059Sigor@sysoev.ru uint16_t length; 1001059Sigor@sysoev.ru } name; 1011059Sigor@sysoev.ru } u; 1021059Sigor@sysoev.ru 103964Sigor@sysoev.ru nxt_http_route_pattern_t pattern[0]; 104964Sigor@sysoev.ru } nxt_http_route_rule_t; 105964Sigor@sysoev.ru 106964Sigor@sysoev.ru 107964Sigor@sysoev.ru typedef struct { 108964Sigor@sysoev.ru uint32_t items; 1091059Sigor@sysoev.ru nxt_http_route_rule_t *rule[0]; 1101059Sigor@sysoev.ru } nxt_http_route_ruleset_t; 1111059Sigor@sysoev.ru 1121059Sigor@sysoev.ru 1131059Sigor@sysoev.ru typedef struct { 1141059Sigor@sysoev.ru /* The object must be the first field. */ 1151059Sigor@sysoev.ru nxt_http_route_object_t object:8; 1161059Sigor@sysoev.ru uint32_t items; 1171059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset[0]; 1181059Sigor@sysoev.ru } nxt_http_route_table_t; 1191059Sigor@sysoev.ru 1201059Sigor@sysoev.ru 1211059Sigor@sysoev.ru typedef union { 1221059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 1231059Sigor@sysoev.ru nxt_http_route_table_t *table; 1241059Sigor@sysoev.ru } nxt_http_route_test_t; 1251059Sigor@sysoev.ru 1261059Sigor@sysoev.ru 1271059Sigor@sysoev.ru typedef struct { 1281059Sigor@sysoev.ru uint32_t items; 1291264Sigor@sysoev.ru nxt_http_action_t action; 1301059Sigor@sysoev.ru nxt_http_route_test_t test[0]; 131964Sigor@sysoev.ru } nxt_http_route_match_t; 132964Sigor@sysoev.ru 133964Sigor@sysoev.ru 134964Sigor@sysoev.ru struct nxt_http_route_s { 135964Sigor@sysoev.ru nxt_str_t name; 136964Sigor@sysoev.ru uint32_t items; 137964Sigor@sysoev.ru nxt_http_route_match_t *match[0]; 138964Sigor@sysoev.ru }; 139964Sigor@sysoev.ru 140964Sigor@sysoev.ru 141964Sigor@sysoev.ru struct nxt_http_routes_s { 142964Sigor@sysoev.ru uint32_t items; 143964Sigor@sysoev.ru nxt_http_route_t *route[0]; 144964Sigor@sysoev.ru }; 145964Sigor@sysoev.ru 146964Sigor@sysoev.ru 1471062Sigor@sysoev.ru #define NJS_COOKIE_HASH \ 1481062Sigor@sysoev.ru (nxt_http_field_hash_end( \ 1491062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1501062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1511062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1521062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1531062Sigor@sysoev.ru nxt_http_field_hash_char( \ 1541062Sigor@sysoev.ru nxt_http_field_hash_char(NXT_HTTP_FIELD_HASH_INIT, \ 1551062Sigor@sysoev.ru 'c'), 'o'), 'o'), 'k'), 'i'), 'e')) & 0xFFFF) 1561062Sigor@sysoev.ru 1571062Sigor@sysoev.ru 158964Sigor@sysoev.ru static nxt_http_route_t *nxt_http_route_create(nxt_task_t *task, 159964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 160964Sigor@sysoev.ru static nxt_http_route_match_t *nxt_http_route_match_create(nxt_task_t *task, 161964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv); 1621264Sigor@sysoev.ru static nxt_int_t nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, 1631264Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_match_t *match); 1641059Sigor@sysoev.ru static nxt_http_route_table_t *nxt_http_route_table_create(nxt_task_t *task, 1651061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 1661061Sigor@sysoev.ru nxt_bool_t case_sensitive); 1671059Sigor@sysoev.ru static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, 1681061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 1691061Sigor@sysoev.ru nxt_bool_t case_sensitive); 1701061Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, 1711061Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, 1721061Sigor@sysoev.ru nxt_bool_t case_sensitive); 173964Sigor@sysoev.ru static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, 1741059Sigor@sysoev.ru nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 1751059Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case); 176964Sigor@sysoev.ru static int nxt_http_pattern_compare(const void *one, const void *two); 177964Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 178964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 179964Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case); 1801032Sigor@sysoev.ru static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, 1811032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case); 182964Sigor@sysoev.ru 183964Sigor@sysoev.ru static void nxt_http_route_resolve(nxt_task_t *task, 184964Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_route_t *route); 1851264Sigor@sysoev.ru static void nxt_http_action_resolve(nxt_task_t *task, 1861264Sigor@sysoev.ru nxt_router_temp_conf_t *tmcf, nxt_http_action_t *action); 187964Sigor@sysoev.ru static nxt_http_route_t *nxt_http_route_find(nxt_http_routes_t *routes, 188964Sigor@sysoev.ru nxt_str_t *name); 189964Sigor@sysoev.ru static void nxt_http_route_cleanup(nxt_task_t *task, nxt_http_route_t *routes); 190964Sigor@sysoev.ru 1911264Sigor@sysoev.ru static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, 1921264Sigor@sysoev.ru nxt_http_request_t *r, nxt_http_action_t *start); 1931264Sigor@sysoev.ru static nxt_http_action_t *nxt_http_route_match(nxt_http_request_t *r, 194964Sigor@sysoev.ru nxt_http_route_match_t *match); 1951060Sigor@sysoev.ru static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, 1961059Sigor@sysoev.ru nxt_http_route_table_t *table); 1971060Sigor@sysoev.ru static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, 1981059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset); 1991060Sigor@sysoev.ru static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, 200964Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2011060Sigor@sysoev.ru static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, 2021059Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2031061Sigor@sysoev.ru static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, 2041061Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2051061Sigor@sysoev.ru static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); 2061061Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, 2071061Sigor@sysoev.ru u_char *name, size_t name_length, uint32_t hash, u_char *start, 2081061Sigor@sysoev.ru u_char *end); 2091061Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_argument(nxt_http_request_t *r, 2101061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2111110Saxel.duch@nginx.com static nxt_int_t nxt_http_route_scheme(nxt_http_request_t *r, 2121110Saxel.duch@nginx.com nxt_http_route_rule_t *rule); 2131062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookies(nxt_http_request_t *r, 2141062Sigor@sysoev.ru nxt_http_route_rule_t *rule); 2151062Sigor@sysoev.ru static nxt_array_t *nxt_http_route_cookies_parse(nxt_http_request_t *r); 2161062Sigor@sysoev.ru static nxt_int_t nxt_http_route_cookie_parse(nxt_array_t *cookies, 2171062Sigor@sysoev.ru u_char *start, u_char *end); 2181062Sigor@sysoev.ru static nxt_http_name_value_t *nxt_http_route_cookie(nxt_array_t *array, 2191062Sigor@sysoev.ru u_char *name, size_t name_length, u_char *start, u_char *end); 2201062Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_cookie(nxt_http_request_t *r, 2211062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array); 2221060Sigor@sysoev.ru static nxt_int_t nxt_http_route_test_rule(nxt_http_request_t *r, 2231059Sigor@sysoev.ru nxt_http_route_rule_t *rule, u_char *start, size_t length); 2241060Sigor@sysoev.ru static nxt_int_t nxt_http_route_pattern(nxt_http_request_t *r, 225964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, u_char *start, size_t length); 2261060Sigor@sysoev.ru static nxt_int_t nxt_http_route_memcmp(u_char *start, u_char *test, 2271032Sigor@sysoev.ru size_t length, nxt_bool_t case_sensitive); 228964Sigor@sysoev.ru 229964Sigor@sysoev.ru 230964Sigor@sysoev.ru nxt_http_routes_t * 231964Sigor@sysoev.ru nxt_http_routes_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 232964Sigor@sysoev.ru nxt_conf_value_t *routes_conf) 233964Sigor@sysoev.ru { 234964Sigor@sysoev.ru size_t size; 235964Sigor@sysoev.ru uint32_t i, n, next; 236964Sigor@sysoev.ru nxt_mp_t *mp; 237964Sigor@sysoev.ru nxt_str_t name, *string; 238964Sigor@sysoev.ru nxt_bool_t object; 239964Sigor@sysoev.ru nxt_conf_value_t *route_conf; 240964Sigor@sysoev.ru nxt_http_route_t *route; 241964Sigor@sysoev.ru nxt_http_routes_t *routes; 242964Sigor@sysoev.ru 243964Sigor@sysoev.ru object = (nxt_conf_type(routes_conf) == NXT_CONF_OBJECT); 244964Sigor@sysoev.ru n = object ? nxt_conf_object_members_count(routes_conf) : 1; 245964Sigor@sysoev.ru size = sizeof(nxt_http_routes_t) + n * sizeof(nxt_http_route_t *); 246964Sigor@sysoev.ru 247964Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 248964Sigor@sysoev.ru 249964Sigor@sysoev.ru routes = nxt_mp_alloc(mp, size); 250964Sigor@sysoev.ru if (nxt_slow_path(routes == NULL)) { 251964Sigor@sysoev.ru return NULL; 252964Sigor@sysoev.ru } 253964Sigor@sysoev.ru 254964Sigor@sysoev.ru routes->items = n; 255964Sigor@sysoev.ru 256964Sigor@sysoev.ru if (object) { 257964Sigor@sysoev.ru next = 0; 258964Sigor@sysoev.ru 259964Sigor@sysoev.ru for (i = 0; i < n; i++) { 260964Sigor@sysoev.ru route_conf = nxt_conf_next_object_member(routes_conf, &name, &next); 261964Sigor@sysoev.ru 262964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, route_conf); 263964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 264964Sigor@sysoev.ru return NULL; 265964Sigor@sysoev.ru } 266964Sigor@sysoev.ru 267964Sigor@sysoev.ru routes->route[i] = route; 268964Sigor@sysoev.ru 269964Sigor@sysoev.ru string = nxt_str_dup(mp, &route->name, &name); 270964Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) { 271964Sigor@sysoev.ru return NULL; 272964Sigor@sysoev.ru } 273964Sigor@sysoev.ru } 274964Sigor@sysoev.ru 275964Sigor@sysoev.ru } else { 276964Sigor@sysoev.ru route = nxt_http_route_create(task, tmcf, routes_conf); 277964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 278964Sigor@sysoev.ru return NULL; 279964Sigor@sysoev.ru } 280964Sigor@sysoev.ru 281964Sigor@sysoev.ru routes->route[0] = route; 282964Sigor@sysoev.ru 283964Sigor@sysoev.ru route->name.length = 0; 284964Sigor@sysoev.ru route->name.start = NULL; 285964Sigor@sysoev.ru } 286964Sigor@sysoev.ru 287964Sigor@sysoev.ru return routes; 288964Sigor@sysoev.ru } 289964Sigor@sysoev.ru 290964Sigor@sysoev.ru 291964Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_match_conf[] = { 292964Sigor@sysoev.ru { 2931110Saxel.duch@nginx.com nxt_string("scheme"), 2941110Saxel.duch@nginx.com NXT_CONF_MAP_PTR, 2951110Saxel.duch@nginx.com offsetof(nxt_http_route_match_conf_t, scheme) 2961110Saxel.duch@nginx.com }, 2971110Saxel.duch@nginx.com { 298964Sigor@sysoev.ru nxt_string("host"), 299964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 300964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, host), 301964Sigor@sysoev.ru }, 302964Sigor@sysoev.ru 303964Sigor@sysoev.ru { 304964Sigor@sysoev.ru nxt_string("uri"), 305964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 306964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, uri), 307964Sigor@sysoev.ru }, 308964Sigor@sysoev.ru 309964Sigor@sysoev.ru { 310964Sigor@sysoev.ru nxt_string("method"), 311964Sigor@sysoev.ru NXT_CONF_MAP_PTR, 312964Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, method), 313964Sigor@sysoev.ru }, 3141059Sigor@sysoev.ru 3151059Sigor@sysoev.ru { 3161059Sigor@sysoev.ru nxt_string("headers"), 3171059Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3181059Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, headers), 3191059Sigor@sysoev.ru }, 3201061Sigor@sysoev.ru 3211061Sigor@sysoev.ru { 3221061Sigor@sysoev.ru nxt_string("arguments"), 3231061Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3241061Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, arguments), 3251061Sigor@sysoev.ru }, 3261062Sigor@sysoev.ru 3271062Sigor@sysoev.ru { 3281062Sigor@sysoev.ru nxt_string("cookies"), 3291062Sigor@sysoev.ru NXT_CONF_MAP_PTR, 3301062Sigor@sysoev.ru offsetof(nxt_http_route_match_conf_t, cookies), 3311062Sigor@sysoev.ru }, 332964Sigor@sysoev.ru }; 333964Sigor@sysoev.ru 334964Sigor@sysoev.ru 335964Sigor@sysoev.ru static nxt_http_route_t * 336964Sigor@sysoev.ru nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 337964Sigor@sysoev.ru nxt_conf_value_t *cv) 338964Sigor@sysoev.ru { 339964Sigor@sysoev.ru size_t size; 340964Sigor@sysoev.ru uint32_t i, n; 341964Sigor@sysoev.ru nxt_conf_value_t *value; 342964Sigor@sysoev.ru nxt_http_route_t *route; 343964Sigor@sysoev.ru nxt_http_route_match_t *match, **m; 344964Sigor@sysoev.ru 345964Sigor@sysoev.ru n = nxt_conf_array_elements_count(cv); 346964Sigor@sysoev.ru size = sizeof(nxt_http_route_t) + n * sizeof(nxt_http_route_match_t *); 347964Sigor@sysoev.ru 348964Sigor@sysoev.ru route = nxt_mp_alloc(tmcf->router_conf->mem_pool, size); 349964Sigor@sysoev.ru if (nxt_slow_path(route == NULL)) { 350964Sigor@sysoev.ru return NULL; 351964Sigor@sysoev.ru } 352964Sigor@sysoev.ru 353964Sigor@sysoev.ru route->items = n; 354964Sigor@sysoev.ru m = &route->match[0]; 355964Sigor@sysoev.ru 356964Sigor@sysoev.ru for (i = 0; i < n; i++) { 357964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i); 358964Sigor@sysoev.ru 359964Sigor@sysoev.ru match = nxt_http_route_match_create(task, tmcf, value); 360964Sigor@sysoev.ru if (match == NULL) { 361964Sigor@sysoev.ru return NULL; 362964Sigor@sysoev.ru } 363964Sigor@sysoev.ru 364964Sigor@sysoev.ru *m++ = match; 365964Sigor@sysoev.ru } 366964Sigor@sysoev.ru 367964Sigor@sysoev.ru return route; 368964Sigor@sysoev.ru } 369964Sigor@sysoev.ru 370964Sigor@sysoev.ru 371964Sigor@sysoev.ru static nxt_http_route_match_t * 372964Sigor@sysoev.ru nxt_http_route_match_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 373964Sigor@sysoev.ru nxt_conf_value_t *cv) 374964Sigor@sysoev.ru { 375964Sigor@sysoev.ru size_t size; 376964Sigor@sysoev.ru uint32_t n; 3771059Sigor@sysoev.ru nxt_mp_t *mp; 378964Sigor@sysoev.ru nxt_int_t ret; 3791264Sigor@sysoev.ru nxt_conf_value_t *match_conf; 3801059Sigor@sysoev.ru nxt_http_route_test_t *test; 3811059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 3821059Sigor@sysoev.ru nxt_http_route_table_t *table; 383964Sigor@sysoev.ru nxt_http_route_match_t *match; 384964Sigor@sysoev.ru nxt_http_route_match_conf_t mtcf; 385964Sigor@sysoev.ru 386964Sigor@sysoev.ru static nxt_str_t match_path = nxt_string("/match"); 387964Sigor@sysoev.ru 388964Sigor@sysoev.ru match_conf = nxt_conf_get_path(cv, &match_path); 389964Sigor@sysoev.ru 390964Sigor@sysoev.ru n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; 391964Sigor@sysoev.ru size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_rule_t *); 392964Sigor@sysoev.ru 3931059Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 3941059Sigor@sysoev.ru 3951059Sigor@sysoev.ru match = nxt_mp_alloc(mp, size); 396964Sigor@sysoev.ru if (nxt_slow_path(match == NULL)) { 397964Sigor@sysoev.ru return NULL; 398964Sigor@sysoev.ru } 399964Sigor@sysoev.ru 4001264Sigor@sysoev.ru match->action.u.route = NULL; 4011264Sigor@sysoev.ru match->action.handler = NULL; 402964Sigor@sysoev.ru match->items = n; 403964Sigor@sysoev.ru 4041264Sigor@sysoev.ru ret = nxt_http_route_action_create(tmcf, cv, match); 4051264Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 406964Sigor@sysoev.ru return NULL; 407964Sigor@sysoev.ru } 408964Sigor@sysoev.ru 409964Sigor@sysoev.ru if (n == 0) { 410964Sigor@sysoev.ru return match; 411964Sigor@sysoev.ru } 412964Sigor@sysoev.ru 413964Sigor@sysoev.ru nxt_memzero(&mtcf, sizeof(mtcf)); 414964Sigor@sysoev.ru 415964Sigor@sysoev.ru ret = nxt_conf_map_object(tmcf->mem_pool, 416964Sigor@sysoev.ru match_conf, nxt_http_route_match_conf, 417964Sigor@sysoev.ru nxt_nitems(nxt_http_route_match_conf), &mtcf); 418964Sigor@sysoev.ru if (ret != NXT_OK) { 419964Sigor@sysoev.ru return NULL; 420964Sigor@sysoev.ru } 421964Sigor@sysoev.ru 4221059Sigor@sysoev.ru test = &match->test[0]; 423964Sigor@sysoev.ru 4241110Saxel.duch@nginx.com if (mtcf.scheme != NULL) { 4251110Saxel.duch@nginx.com rule = nxt_http_route_rule_create(task, mp, mtcf.scheme, 1, 4261110Saxel.duch@nginx.com NXT_HTTP_ROUTE_PATTERN_NOCASE); 4271110Saxel.duch@nginx.com if (rule == NULL) { 4281110Saxel.duch@nginx.com return NULL; 4291110Saxel.duch@nginx.com } 4301110Saxel.duch@nginx.com 4311110Saxel.duch@nginx.com rule->object = NXT_HTTP_ROUTE_SCHEME; 4321110Saxel.duch@nginx.com test->rule = rule; 4331110Saxel.duch@nginx.com test++; 4341110Saxel.duch@nginx.com } 4351110Saxel.duch@nginx.com 436964Sigor@sysoev.ru if (mtcf.host != NULL) { 4371059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.host, 1, 438964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_LOWCASE); 439964Sigor@sysoev.ru if (rule == NULL) { 440964Sigor@sysoev.ru return NULL; 441964Sigor@sysoev.ru } 442964Sigor@sysoev.ru 4431059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, host); 444964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING; 4451059Sigor@sysoev.ru test->rule = rule; 4461059Sigor@sysoev.ru test++; 447964Sigor@sysoev.ru } 448964Sigor@sysoev.ru 449964Sigor@sysoev.ru if (mtcf.uri != NULL) { 4501059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.uri, 1, 451964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_NOCASE); 452964Sigor@sysoev.ru if (rule == NULL) { 453964Sigor@sysoev.ru return NULL; 454964Sigor@sysoev.ru } 455964Sigor@sysoev.ru 4561059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, path); 457964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 4581059Sigor@sysoev.ru test->rule = rule; 4591059Sigor@sysoev.ru test++; 460964Sigor@sysoev.ru } 461964Sigor@sysoev.ru 462964Sigor@sysoev.ru if (mtcf.method != NULL) { 4631059Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, mtcf.method, 1, 464964Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_UPCASE); 465964Sigor@sysoev.ru if (rule == NULL) { 466964Sigor@sysoev.ru return NULL; 467964Sigor@sysoev.ru } 468964Sigor@sysoev.ru 4691059Sigor@sysoev.ru rule->u.offset = offsetof(nxt_http_request_t, method); 470964Sigor@sysoev.ru rule->object = NXT_HTTP_ROUTE_STRING_PTR; 4711059Sigor@sysoev.ru test->rule = rule; 4721059Sigor@sysoev.ru test++; 4731059Sigor@sysoev.ru } 4741059Sigor@sysoev.ru 4751059Sigor@sysoev.ru if (mtcf.headers != NULL) { 4761061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.headers, 4771061Sigor@sysoev.ru NXT_HTTP_ROUTE_HEADER, 0); 4781061Sigor@sysoev.ru if (table == NULL) { 4791061Sigor@sysoev.ru return NULL; 4801061Sigor@sysoev.ru } 4811061Sigor@sysoev.ru 4821061Sigor@sysoev.ru test->table = table; 4831061Sigor@sysoev.ru test++; 4841061Sigor@sysoev.ru } 4851061Sigor@sysoev.ru 4861061Sigor@sysoev.ru if (mtcf.arguments != NULL) { 4871061Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.arguments, 4881061Sigor@sysoev.ru NXT_HTTP_ROUTE_ARGUMENT, 1); 4891059Sigor@sysoev.ru if (table == NULL) { 4901059Sigor@sysoev.ru return NULL; 4911059Sigor@sysoev.ru } 4921059Sigor@sysoev.ru 4931059Sigor@sysoev.ru test->table = table; 4941059Sigor@sysoev.ru test++; 495964Sigor@sysoev.ru } 496964Sigor@sysoev.ru 4971062Sigor@sysoev.ru if (mtcf.cookies != NULL) { 4981062Sigor@sysoev.ru table = nxt_http_route_table_create(task, mp, mtcf.cookies, 4991079Sigor@sysoev.ru NXT_HTTP_ROUTE_COOKIE, 1); 5001062Sigor@sysoev.ru if (table == NULL) { 5011062Sigor@sysoev.ru return NULL; 5021062Sigor@sysoev.ru } 5031062Sigor@sysoev.ru 5041062Sigor@sysoev.ru test->table = table; 5051062Sigor@sysoev.ru test++; 5061062Sigor@sysoev.ru } 5071062Sigor@sysoev.ru 508964Sigor@sysoev.ru return match; 509964Sigor@sysoev.ru } 510964Sigor@sysoev.ru 511964Sigor@sysoev.ru 5121264Sigor@sysoev.ru static nxt_conf_map_t nxt_http_route_action_conf[] = { 5131264Sigor@sysoev.ru { 5141264Sigor@sysoev.ru nxt_string("pass"), 5151264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 5161264Sigor@sysoev.ru offsetof(nxt_http_route_action_conf_t, pass) 5171264Sigor@sysoev.ru }, 5181264Sigor@sysoev.ru { 5191264Sigor@sysoev.ru nxt_string("share"), 5201264Sigor@sysoev.ru NXT_CONF_MAP_PTR, 5211264Sigor@sysoev.ru offsetof(nxt_http_route_action_conf_t, share) 5221264Sigor@sysoev.ru }, 523*1270Sigor@sysoev.ru { 524*1270Sigor@sysoev.ru nxt_string("proxy"), 525*1270Sigor@sysoev.ru NXT_CONF_MAP_PTR, 526*1270Sigor@sysoev.ru offsetof(nxt_http_route_action_conf_t, proxy) 527*1270Sigor@sysoev.ru }, 5281264Sigor@sysoev.ru }; 5291264Sigor@sysoev.ru 5301264Sigor@sysoev.ru 5311264Sigor@sysoev.ru static nxt_int_t 5321264Sigor@sysoev.ru nxt_http_route_action_create(nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *cv, 5331264Sigor@sysoev.ru nxt_http_route_match_t *match) 5341264Sigor@sysoev.ru { 535*1270Sigor@sysoev.ru nxt_mp_t *mp; 5361264Sigor@sysoev.ru nxt_int_t ret; 5371264Sigor@sysoev.ru nxt_str_t name, *string; 5381264Sigor@sysoev.ru nxt_conf_value_t *conf, *action_conf; 5391264Sigor@sysoev.ru nxt_http_route_action_conf_t accf; 5401264Sigor@sysoev.ru 5411264Sigor@sysoev.ru static nxt_str_t action_path = nxt_string("/action"); 5421264Sigor@sysoev.ru 5431264Sigor@sysoev.ru action_conf = nxt_conf_get_path(cv, &action_path); 5441264Sigor@sysoev.ru if (action_conf == NULL) { 5451264Sigor@sysoev.ru return NXT_ERROR; 5461264Sigor@sysoev.ru } 5471264Sigor@sysoev.ru 5481264Sigor@sysoev.ru nxt_memzero(&accf, sizeof(accf)); 5491264Sigor@sysoev.ru 5501264Sigor@sysoev.ru ret = nxt_conf_map_object(tmcf->mem_pool, 5511264Sigor@sysoev.ru action_conf, nxt_http_route_action_conf, 5521264Sigor@sysoev.ru nxt_nitems(nxt_http_route_action_conf), &accf); 5531264Sigor@sysoev.ru if (ret != NXT_OK) { 5541264Sigor@sysoev.ru return ret; 5551264Sigor@sysoev.ru } 5561264Sigor@sysoev.ru 5571264Sigor@sysoev.ru conf = accf.pass; 5581264Sigor@sysoev.ru 5591264Sigor@sysoev.ru if (accf.share != NULL) { 5601264Sigor@sysoev.ru conf = accf.share; 5611264Sigor@sysoev.ru match->action.handler = nxt_http_static_handler; 562*1270Sigor@sysoev.ru 563*1270Sigor@sysoev.ru } else if (accf.proxy != NULL) { 564*1270Sigor@sysoev.ru conf = accf.proxy; 5651264Sigor@sysoev.ru } 5661264Sigor@sysoev.ru 5671264Sigor@sysoev.ru nxt_conf_get_string(conf, &name); 5681264Sigor@sysoev.ru 569*1270Sigor@sysoev.ru mp = tmcf->router_conf->mem_pool; 570*1270Sigor@sysoev.ru 571*1270Sigor@sysoev.ru string = nxt_str_dup(mp, &match->action.name, &name); 5721264Sigor@sysoev.ru if (nxt_slow_path(string == NULL)) { 5731264Sigor@sysoev.ru return NXT_ERROR; 5741264Sigor@sysoev.ru } 5751264Sigor@sysoev.ru 576*1270Sigor@sysoev.ru if (accf.proxy != NULL) { 577*1270Sigor@sysoev.ru return nxt_http_proxy_create(mp, &match->action); 578*1270Sigor@sysoev.ru } 579*1270Sigor@sysoev.ru 5801264Sigor@sysoev.ru return NXT_OK; 5811264Sigor@sysoev.ru } 5821264Sigor@sysoev.ru 5831264Sigor@sysoev.ru 5841059Sigor@sysoev.ru static nxt_http_route_table_t * 5851059Sigor@sysoev.ru nxt_http_route_table_create(nxt_task_t *task, nxt_mp_t *mp, 5861061Sigor@sysoev.ru nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 5871061Sigor@sysoev.ru nxt_bool_t case_sensitive) 5881059Sigor@sysoev.ru { 5891059Sigor@sysoev.ru size_t size; 5901059Sigor@sysoev.ru uint32_t i, n; 5911059Sigor@sysoev.ru nxt_bool_t array; 5921059Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv; 5931059Sigor@sysoev.ru nxt_http_route_table_t *table; 5941059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 5951059Sigor@sysoev.ru 5961059Sigor@sysoev.ru array = (nxt_conf_type(table_cv) == NXT_CONF_ARRAY); 5971059Sigor@sysoev.ru n = array ? nxt_conf_array_elements_count(table_cv) : 1; 5981059Sigor@sysoev.ru size = sizeof(nxt_http_route_table_t) 5991059Sigor@sysoev.ru + n * sizeof(nxt_http_route_ruleset_t *); 6001059Sigor@sysoev.ru 6011059Sigor@sysoev.ru table = nxt_mp_alloc(mp, size); 6021059Sigor@sysoev.ru if (nxt_slow_path(table == NULL)) { 6031059Sigor@sysoev.ru return NULL; 6041059Sigor@sysoev.ru } 6051059Sigor@sysoev.ru 6061059Sigor@sysoev.ru table->items = n; 6071059Sigor@sysoev.ru table->object = NXT_HTTP_ROUTE_TABLE; 6081059Sigor@sysoev.ru 6091059Sigor@sysoev.ru if (!array) { 6101061Sigor@sysoev.ru ruleset = nxt_http_route_ruleset_create(task, mp, table_cv, 6111061Sigor@sysoev.ru object, case_sensitive); 6121059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 6131059Sigor@sysoev.ru return NULL; 6141059Sigor@sysoev.ru } 6151059Sigor@sysoev.ru 6161059Sigor@sysoev.ru table->ruleset[0] = ruleset; 6171059Sigor@sysoev.ru 6181059Sigor@sysoev.ru return table; 6191059Sigor@sysoev.ru } 6201059Sigor@sysoev.ru 6211059Sigor@sysoev.ru for (i = 0; i < n; i++) { 6221059Sigor@sysoev.ru ruleset_cv = nxt_conf_get_array_element(table_cv, i); 6231059Sigor@sysoev.ru 6241061Sigor@sysoev.ru ruleset = nxt_http_route_ruleset_create(task, mp, ruleset_cv, 6251061Sigor@sysoev.ru object, case_sensitive); 6261059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 6271059Sigor@sysoev.ru return NULL; 6281059Sigor@sysoev.ru } 6291059Sigor@sysoev.ru 6301059Sigor@sysoev.ru table->ruleset[i] = ruleset; 6311059Sigor@sysoev.ru } 6321059Sigor@sysoev.ru 6331059Sigor@sysoev.ru return table; 6341059Sigor@sysoev.ru } 6351059Sigor@sysoev.ru 6361059Sigor@sysoev.ru 6371059Sigor@sysoev.ru static nxt_http_route_ruleset_t * 6381059Sigor@sysoev.ru nxt_http_route_ruleset_create(nxt_task_t *task, nxt_mp_t *mp, 6391061Sigor@sysoev.ru nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 6401061Sigor@sysoev.ru nxt_bool_t case_sensitive) 6411059Sigor@sysoev.ru { 6421059Sigor@sysoev.ru size_t size; 6431059Sigor@sysoev.ru uint32_t i, n, next; 6441059Sigor@sysoev.ru nxt_str_t name; 6451059Sigor@sysoev.ru nxt_conf_value_t *rule_cv; 6461059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 6471059Sigor@sysoev.ru nxt_http_route_ruleset_t *ruleset; 6481059Sigor@sysoev.ru 6491059Sigor@sysoev.ru n = nxt_conf_object_members_count(ruleset_cv); 6501059Sigor@sysoev.ru size = sizeof(nxt_http_route_ruleset_t) 6511059Sigor@sysoev.ru + n * sizeof(nxt_http_route_rule_t *); 6521059Sigor@sysoev.ru 6531059Sigor@sysoev.ru ruleset = nxt_mp_alloc(mp, size); 6541059Sigor@sysoev.ru if (nxt_slow_path(ruleset == NULL)) { 6551059Sigor@sysoev.ru return NULL; 6561059Sigor@sysoev.ru } 6571059Sigor@sysoev.ru 6581059Sigor@sysoev.ru ruleset->items = n; 6591059Sigor@sysoev.ru 6601059Sigor@sysoev.ru next = 0; 6611059Sigor@sysoev.ru 6621059Sigor@sysoev.ru for (i = 0; i < n; i++) { 6631059Sigor@sysoev.ru rule_cv = nxt_conf_next_object_member(ruleset_cv, &name, &next); 6641059Sigor@sysoev.ru 6651061Sigor@sysoev.ru rule = nxt_http_route_rule_name_create(task, mp, rule_cv, &name, 6661061Sigor@sysoev.ru case_sensitive); 6671059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 6681059Sigor@sysoev.ru return NULL; 6691059Sigor@sysoev.ru } 6701059Sigor@sysoev.ru 6711061Sigor@sysoev.ru rule->object = object; 6721059Sigor@sysoev.ru ruleset->rule[i] = rule; 6731059Sigor@sysoev.ru } 6741059Sigor@sysoev.ru 6751059Sigor@sysoev.ru return ruleset; 6761059Sigor@sysoev.ru } 6771059Sigor@sysoev.ru 6781059Sigor@sysoev.ru 679964Sigor@sysoev.ru static nxt_http_route_rule_t * 6801061Sigor@sysoev.ru nxt_http_route_rule_name_create(nxt_task_t *task, nxt_mp_t *mp, 6811061Sigor@sysoev.ru nxt_conf_value_t *rule_cv, nxt_str_t *name, nxt_bool_t case_sensitive) 6821059Sigor@sysoev.ru { 6831059Sigor@sysoev.ru u_char c, *p; 6841059Sigor@sysoev.ru uint32_t hash; 6851059Sigor@sysoev.ru nxt_uint_t i; 6861059Sigor@sysoev.ru nxt_http_route_rule_t *rule; 6871059Sigor@sysoev.ru 6881061Sigor@sysoev.ru rule = nxt_http_route_rule_create(task, mp, rule_cv, case_sensitive, 6891059Sigor@sysoev.ru NXT_HTTP_ROUTE_PATTERN_NOCASE); 6901059Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 6911059Sigor@sysoev.ru return NULL; 6921059Sigor@sysoev.ru } 6931059Sigor@sysoev.ru 6941059Sigor@sysoev.ru rule->u.name.length = name->length; 6951059Sigor@sysoev.ru 6961059Sigor@sysoev.ru p = nxt_mp_nget(mp, name->length); 6971059Sigor@sysoev.ru if (nxt_slow_path(p == NULL)) { 6981059Sigor@sysoev.ru return NULL; 6991059Sigor@sysoev.ru } 7001059Sigor@sysoev.ru 7011059Sigor@sysoev.ru rule->u.name.start = p; 7021059Sigor@sysoev.ru 7031059Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 7041059Sigor@sysoev.ru 7051059Sigor@sysoev.ru for (i = 0; i < name->length; i++) { 7061059Sigor@sysoev.ru c = name->start[i]; 7071059Sigor@sysoev.ru *p++ = c; 7081059Sigor@sysoev.ru 7091079Sigor@sysoev.ru c = case_sensitive ? c : nxt_lowcase(c); 7101059Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 7111059Sigor@sysoev.ru } 7121059Sigor@sysoev.ru 7131059Sigor@sysoev.ru rule->u.name.hash = nxt_http_field_hash_end(hash) & 0xFFFF; 7141059Sigor@sysoev.ru 7151059Sigor@sysoev.ru return rule; 7161059Sigor@sysoev.ru } 7171059Sigor@sysoev.ru 7181059Sigor@sysoev.ru 7191059Sigor@sysoev.ru static nxt_http_route_rule_t * 7201059Sigor@sysoev.ru nxt_http_route_rule_create(nxt_task_t *task, nxt_mp_t *mp, 721964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 722964Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case) 723964Sigor@sysoev.ru { 724964Sigor@sysoev.ru size_t size; 725964Sigor@sysoev.ru uint32_t i, n; 726964Sigor@sysoev.ru nxt_int_t ret; 727964Sigor@sysoev.ru nxt_bool_t string; 728964Sigor@sysoev.ru nxt_conf_value_t *value; 729964Sigor@sysoev.ru nxt_http_route_rule_t *rule; 730964Sigor@sysoev.ru nxt_http_route_pattern_t *pattern; 731964Sigor@sysoev.ru 732964Sigor@sysoev.ru string = (nxt_conf_type(cv) != NXT_CONF_ARRAY); 733964Sigor@sysoev.ru n = string ? 1 : nxt_conf_array_elements_count(cv); 734964Sigor@sysoev.ru size = sizeof(nxt_http_route_rule_t) + n * sizeof(nxt_http_route_pattern_t); 735964Sigor@sysoev.ru 736964Sigor@sysoev.ru rule = nxt_mp_alloc(mp, size); 737964Sigor@sysoev.ru if (nxt_slow_path(rule == NULL)) { 738964Sigor@sysoev.ru return NULL; 739964Sigor@sysoev.ru } 740964Sigor@sysoev.ru 741964Sigor@sysoev.ru rule->items = n; 742964Sigor@sysoev.ru 743964Sigor@sysoev.ru pattern = &rule->pattern[0]; 744964Sigor@sysoev.ru 745964Sigor@sysoev.ru if (string) { 746964Sigor@sysoev.ru pattern[0].case_sensitive = case_sensitive; 747964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, cv, &pattern[0], 748964Sigor@sysoev.ru pattern_case); 749964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 750964Sigor@sysoev.ru return NULL; 751964Sigor@sysoev.ru } 752964Sigor@sysoev.ru 753964Sigor@sysoev.ru return rule; 754964Sigor@sysoev.ru } 755964Sigor@sysoev.ru 756964Sigor@sysoev.ru nxt_conf_array_qsort(cv, nxt_http_pattern_compare); 757964Sigor@sysoev.ru 758964Sigor@sysoev.ru for (i = 0; i < n; i++) { 759964Sigor@sysoev.ru pattern[i].case_sensitive = case_sensitive; 760964Sigor@sysoev.ru value = nxt_conf_get_array_element(cv, i); 761964Sigor@sysoev.ru 762964Sigor@sysoev.ru ret = nxt_http_route_pattern_create(task, mp, value, &pattern[i], 763964Sigor@sysoev.ru pattern_case); 764964Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 765964Sigor@sysoev.ru return NULL; 766964Sigor@sysoev.ru } 767964Sigor@sysoev.ru } 768964Sigor@sysoev.ru 769964Sigor@sysoev.ru return rule; 770964Sigor@sysoev.ru } 771964Sigor@sysoev.ru 772964Sigor@sysoev.ru 773964Sigor@sysoev.ru static int 774964Sigor@sysoev.ru nxt_http_pattern_compare(const void *one, const void *two) 775964Sigor@sysoev.ru { 776964Sigor@sysoev.ru nxt_str_t test; 777964Sigor@sysoev.ru nxt_bool_t negative1, negative2; 778964Sigor@sysoev.ru nxt_conf_value_t *value; 779964Sigor@sysoev.ru 780964Sigor@sysoev.ru value = (nxt_conf_value_t *) one; 781964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 782964Sigor@sysoev.ru negative1 = (test.length != 0 && test.start[0] == '!'); 783964Sigor@sysoev.ru 784964Sigor@sysoev.ru value = (nxt_conf_value_t *) two; 785964Sigor@sysoev.ru nxt_conf_get_string(value, &test); 786964Sigor@sysoev.ru negative2 = (test.length != 0 && test.start[0] == '!'); 787964Sigor@sysoev.ru 788964Sigor@sysoev.ru return (negative2 - negative1); 789964Sigor@sysoev.ru } 790964Sigor@sysoev.ru 791964Sigor@sysoev.ru 792964Sigor@sysoev.ru static nxt_int_t 793964Sigor@sysoev.ru nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 794964Sigor@sysoev.ru nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 795964Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case) 796964Sigor@sysoev.ru { 797964Sigor@sysoev.ru u_char *start; 798964Sigor@sysoev.ru nxt_str_t test; 7991032Sigor@sysoev.ru nxt_uint_t n, length; 800964Sigor@sysoev.ru nxt_http_route_pattern_type_t type; 801964Sigor@sysoev.ru 8021032Sigor@sysoev.ru /* Suppress warning about uninitialized variable. */ 8031032Sigor@sysoev.ru length = 0; 8041032Sigor@sysoev.ru 805964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_EXACT; 806964Sigor@sysoev.ru 807964Sigor@sysoev.ru nxt_conf_get_string(cv, &test); 808964Sigor@sysoev.ru 809964Sigor@sysoev.ru pattern->negative = 0; 810964Sigor@sysoev.ru pattern->any = 1; 811964Sigor@sysoev.ru 812964Sigor@sysoev.ru if (test.length != 0) { 813964Sigor@sysoev.ru 814964Sigor@sysoev.ru if (test.start[0] == '!') { 815964Sigor@sysoev.ru test.start++; 816964Sigor@sysoev.ru test.length--; 817964Sigor@sysoev.ru 818964Sigor@sysoev.ru pattern->negative = 1; 819964Sigor@sysoev.ru pattern->any = 0; 820964Sigor@sysoev.ru } 821964Sigor@sysoev.ru 822964Sigor@sysoev.ru if (test.length != 0) { 823964Sigor@sysoev.ru 824964Sigor@sysoev.ru if (test.start[0] == '*') { 825964Sigor@sysoev.ru test.start++; 826964Sigor@sysoev.ru test.length--; 827964Sigor@sysoev.ru 828964Sigor@sysoev.ru if (test.length != 0) { 829964Sigor@sysoev.ru if (test.start[test.length - 1] == '*') { 830964Sigor@sysoev.ru test.length--; 831964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_SUBSTRING; 832964Sigor@sysoev.ru 833964Sigor@sysoev.ru } else { 834964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_END; 835964Sigor@sysoev.ru } 836964Sigor@sysoev.ru 837964Sigor@sysoev.ru } else { 838964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_BEGIN; 839964Sigor@sysoev.ru } 840964Sigor@sysoev.ru 841964Sigor@sysoev.ru } else if (test.start[test.length - 1] == '*') { 842964Sigor@sysoev.ru test.length--; 843964Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_BEGIN; 8441032Sigor@sysoev.ru 8451032Sigor@sysoev.ru } else { 8461032Sigor@sysoev.ru length = test.length - 1; 8471032Sigor@sysoev.ru 8481032Sigor@sysoev.ru for (n = 1; n < length; n++) { 8491032Sigor@sysoev.ru if (test.start[n] == '*') { 8501032Sigor@sysoev.ru test.length = n; 8511032Sigor@sysoev.ru type = NXT_HTTP_ROUTE_PATTERN_MIDDLE; 8521032Sigor@sysoev.ru break; 8531032Sigor@sysoev.ru } 8541032Sigor@sysoev.ru } 855964Sigor@sysoev.ru } 856964Sigor@sysoev.ru } 857964Sigor@sysoev.ru } 858964Sigor@sysoev.ru 859964Sigor@sysoev.ru pattern->type = type; 860964Sigor@sysoev.ru pattern->min_length = test.length; 8611032Sigor@sysoev.ru pattern->length1 = test.length; 862964Sigor@sysoev.ru 8631032Sigor@sysoev.ru start = nxt_http_route_pattern_copy(mp, &test, pattern_case); 864964Sigor@sysoev.ru if (nxt_slow_path(start == NULL)) { 865964Sigor@sysoev.ru return NXT_ERROR; 866964Sigor@sysoev.ru } 867964Sigor@sysoev.ru 8681032Sigor@sysoev.ru pattern->start1 = start; 8691032Sigor@sysoev.ru 8701032Sigor@sysoev.ru if (type == NXT_HTTP_ROUTE_PATTERN_MIDDLE) { 8711032Sigor@sysoev.ru length -= test.length; 8721032Sigor@sysoev.ru pattern->length2 = length; 8731032Sigor@sysoev.ru pattern->min_length += length; 8741032Sigor@sysoev.ru 8751032Sigor@sysoev.ru test.start = &test.start[test.length + 1]; 8761032Sigor@sysoev.ru test.length = length; 8771032Sigor@sysoev.ru 8781032Sigor@sysoev.ru start = nxt_http_route_pattern_copy(mp, &test, pattern_case); 8791032Sigor@sysoev.ru if (nxt_slow_path(start == NULL)) { 8801032Sigor@sysoev.ru return NXT_ERROR; 8811032Sigor@sysoev.ru } 8821032Sigor@sysoev.ru 8831032Sigor@sysoev.ru pattern->start2 = start; 8841032Sigor@sysoev.ru } 8851032Sigor@sysoev.ru 8861032Sigor@sysoev.ru return NXT_OK; 8871032Sigor@sysoev.ru } 8881032Sigor@sysoev.ru 8891032Sigor@sysoev.ru 8901032Sigor@sysoev.ru static u_char * 8911032Sigor@sysoev.ru nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, 8921032Sigor@sysoev.ru nxt_http_route_pattern_case_t pattern_case) 8931032Sigor@sysoev.ru { 8941032Sigor@sysoev.ru u_char *start; 8951032Sigor@sysoev.ru 8961032Sigor@sysoev.ru start = nxt_mp_nget(mp, test->length); 8971032Sigor@sysoev.ru if (nxt_slow_path(start == NULL)) { 8981032Sigor@sysoev.ru return start; 8991032Sigor@sysoev.ru } 900964Sigor@sysoev.ru 901964Sigor@sysoev.ru switch (pattern_case) { 902964Sigor@sysoev.ru 903964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_UPCASE: 9041032Sigor@sysoev.ru nxt_memcpy_upcase(start, test->start, test->length); 905964Sigor@sysoev.ru break; 906964Sigor@sysoev.ru 907964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_LOWCASE: 9081032Sigor@sysoev.ru nxt_memcpy_lowcase(start, test->start, test->length); 909964Sigor@sysoev.ru break; 910964Sigor@sysoev.ru 911964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_NOCASE: 9121032Sigor@sysoev.ru nxt_memcpy(start, test->start, test->length); 913964Sigor@sysoev.ru break; 914964Sigor@sysoev.ru } 915964Sigor@sysoev.ru 9161032Sigor@sysoev.ru return start; 917964Sigor@sysoev.ru } 918964Sigor@sysoev.ru 919964Sigor@sysoev.ru 920964Sigor@sysoev.ru void 921964Sigor@sysoev.ru nxt_http_routes_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf) 922964Sigor@sysoev.ru { 9231033Svbart@nginx.com nxt_http_route_t **route, **end; 924964Sigor@sysoev.ru nxt_http_routes_t *routes; 925964Sigor@sysoev.ru 926964Sigor@sysoev.ru routes = tmcf->router_conf->routes; 9271059Sigor@sysoev.ru 928964Sigor@sysoev.ru if (routes != NULL) { 929964Sigor@sysoev.ru route = &routes->route[0]; 9301033Svbart@nginx.com end = route + routes->items; 931964Sigor@sysoev.ru 9321033Svbart@nginx.com while (route < end) { 933964Sigor@sysoev.ru nxt_http_route_resolve(task, tmcf, *route); 934964Sigor@sysoev.ru 935964Sigor@sysoev.ru route++; 936964Sigor@sysoev.ru } 937964Sigor@sysoev.ru } 938964Sigor@sysoev.ru } 939964Sigor@sysoev.ru 940964Sigor@sysoev.ru 941964Sigor@sysoev.ru static void 942964Sigor@sysoev.ru nxt_http_route_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 943964Sigor@sysoev.ru nxt_http_route_t *route) 944964Sigor@sysoev.ru { 9451264Sigor@sysoev.ru nxt_http_action_t *action; 9461033Svbart@nginx.com nxt_http_route_match_t **match, **end; 947964Sigor@sysoev.ru 948964Sigor@sysoev.ru match = &route->match[0]; 9491033Svbart@nginx.com end = match + route->items; 950964Sigor@sysoev.ru 9511033Svbart@nginx.com while (match < end) { 9521264Sigor@sysoev.ru action = &(*match)->action; 9531183Svbart@nginx.com 9541264Sigor@sysoev.ru if (action->handler == NULL) { 9551264Sigor@sysoev.ru nxt_http_action_resolve(task, tmcf, &(*match)->action); 9561183Svbart@nginx.com } 957964Sigor@sysoev.ru 958964Sigor@sysoev.ru match++; 959964Sigor@sysoev.ru } 960964Sigor@sysoev.ru } 961964Sigor@sysoev.ru 962964Sigor@sysoev.ru 963964Sigor@sysoev.ru static void 9641264Sigor@sysoev.ru nxt_http_action_resolve(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 9651264Sigor@sysoev.ru nxt_http_action_t *action) 966964Sigor@sysoev.ru { 967964Sigor@sysoev.ru nxt_str_t name; 968964Sigor@sysoev.ru 9691264Sigor@sysoev.ru name = action->name; 970964Sigor@sysoev.ru 971964Sigor@sysoev.ru if (nxt_str_start(&name, "applications/", 13)) { 972964Sigor@sysoev.ru name.length -= 13; 973964Sigor@sysoev.ru name.start += 13; 974964Sigor@sysoev.ru 9751264Sigor@sysoev.ru action->u.application = nxt_router_listener_application(tmcf, &name); 9761264Sigor@sysoev.ru nxt_router_app_use(task, action->u.application, 1); 977964Sigor@sysoev.ru 9781264Sigor@sysoev.ru action->handler = nxt_http_application_handler; 979964Sigor@sysoev.ru 980964Sigor@sysoev.ru } else if (nxt_str_start(&name, "routes", 6)) { 981964Sigor@sysoev.ru 982964Sigor@sysoev.ru if (name.length == 6) { 983964Sigor@sysoev.ru name.length = 0; 984964Sigor@sysoev.ru name.start = NULL; 985964Sigor@sysoev.ru 986964Sigor@sysoev.ru } else if (name.start[6] == '/') { 987964Sigor@sysoev.ru name.length -= 7; 988964Sigor@sysoev.ru name.start += 7; 989964Sigor@sysoev.ru } 990964Sigor@sysoev.ru 9911264Sigor@sysoev.ru action->u.route = nxt_http_route_find(tmcf->router_conf->routes, &name); 992964Sigor@sysoev.ru 9931264Sigor@sysoev.ru action->handler = nxt_http_route_handler; 994964Sigor@sysoev.ru } 995964Sigor@sysoev.ru } 996964Sigor@sysoev.ru 997964Sigor@sysoev.ru 998964Sigor@sysoev.ru static nxt_http_route_t * 999964Sigor@sysoev.ru nxt_http_route_find(nxt_http_routes_t *routes, nxt_str_t *name) 1000964Sigor@sysoev.ru { 10011033Svbart@nginx.com nxt_http_route_t **route, **end; 1002964Sigor@sysoev.ru 1003964Sigor@sysoev.ru route = &routes->route[0]; 10041033Svbart@nginx.com end = route + routes->items; 1005964Sigor@sysoev.ru 10061058Sigor@sysoev.ru while (route < end) { 1007964Sigor@sysoev.ru if (nxt_strstr_eq(&(*route)->name, name)) { 1008964Sigor@sysoev.ru return *route; 1009964Sigor@sysoev.ru } 1010964Sigor@sysoev.ru 1011964Sigor@sysoev.ru route++; 10121058Sigor@sysoev.ru } 1013964Sigor@sysoev.ru 1014964Sigor@sysoev.ru return NULL; 1015964Sigor@sysoev.ru } 1016964Sigor@sysoev.ru 1017964Sigor@sysoev.ru 10181264Sigor@sysoev.ru nxt_http_action_t * 10191264Sigor@sysoev.ru nxt_http_action_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1020964Sigor@sysoev.ru nxt_str_t *name) 1021964Sigor@sysoev.ru { 10221264Sigor@sysoev.ru nxt_http_action_t *action; 1023964Sigor@sysoev.ru 10241264Sigor@sysoev.ru action = nxt_mp_alloc(tmcf->router_conf->mem_pool, 10251264Sigor@sysoev.ru sizeof(nxt_http_action_t)); 10261264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1027964Sigor@sysoev.ru return NULL; 1028964Sigor@sysoev.ru } 1029964Sigor@sysoev.ru 10301264Sigor@sysoev.ru action->name = *name; 1031*1270Sigor@sysoev.ru action->handler = NULL; 1032964Sigor@sysoev.ru 10331264Sigor@sysoev.ru nxt_http_action_resolve(task, tmcf, action); 1034964Sigor@sysoev.ru 10351264Sigor@sysoev.ru return action; 1036964Sigor@sysoev.ru } 1037964Sigor@sysoev.ru 1038964Sigor@sysoev.ru 1039964Sigor@sysoev.ru /* COMPATIBILITY: listener application. */ 1040964Sigor@sysoev.ru 10411264Sigor@sysoev.ru nxt_http_action_t * 1042964Sigor@sysoev.ru nxt_http_pass_application(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 1043964Sigor@sysoev.ru nxt_str_t *name) 1044964Sigor@sysoev.ru { 10451264Sigor@sysoev.ru nxt_http_action_t *action; 1046964Sigor@sysoev.ru 10471264Sigor@sysoev.ru action = nxt_mp_alloc(tmcf->router_conf->mem_pool, 10481264Sigor@sysoev.ru sizeof(nxt_http_action_t)); 10491264Sigor@sysoev.ru if (nxt_slow_path(action == NULL)) { 1050964Sigor@sysoev.ru return NULL; 1051964Sigor@sysoev.ru } 1052964Sigor@sysoev.ru 10531264Sigor@sysoev.ru action->name = *name; 1054964Sigor@sysoev.ru 10551264Sigor@sysoev.ru action->u.application = nxt_router_listener_application(tmcf, name); 10561264Sigor@sysoev.ru nxt_router_app_use(task, action->u.application, 1); 1057964Sigor@sysoev.ru 10581264Sigor@sysoev.ru action->handler = nxt_http_application_handler; 1059964Sigor@sysoev.ru 10601264Sigor@sysoev.ru return action; 1061964Sigor@sysoev.ru } 1062964Sigor@sysoev.ru 1063964Sigor@sysoev.ru 1064964Sigor@sysoev.ru void 1065964Sigor@sysoev.ru nxt_http_routes_cleanup(nxt_task_t *task, nxt_http_routes_t *routes) 1066964Sigor@sysoev.ru { 10671033Svbart@nginx.com nxt_http_route_t **route, **end; 1068964Sigor@sysoev.ru 1069964Sigor@sysoev.ru if (routes != NULL) { 1070964Sigor@sysoev.ru route = &routes->route[0]; 10711033Svbart@nginx.com end = route + routes->items; 1072964Sigor@sysoev.ru 10731058Sigor@sysoev.ru while (route < end) { 1074964Sigor@sysoev.ru nxt_http_route_cleanup(task, *route); 1075964Sigor@sysoev.ru 1076964Sigor@sysoev.ru route++; 10771058Sigor@sysoev.ru } 1078964Sigor@sysoev.ru } 1079964Sigor@sysoev.ru } 1080964Sigor@sysoev.ru 1081964Sigor@sysoev.ru 1082964Sigor@sysoev.ru static void 1083964Sigor@sysoev.ru nxt_http_route_cleanup(nxt_task_t *task, nxt_http_route_t *route) 1084964Sigor@sysoev.ru { 10851033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1086964Sigor@sysoev.ru 1087964Sigor@sysoev.ru match = &route->match[0]; 10881033Svbart@nginx.com end = match + route->items; 1089964Sigor@sysoev.ru 10901058Sigor@sysoev.ru while (match < end) { 10911264Sigor@sysoev.ru nxt_http_action_cleanup(task, &(*match)->action); 1092964Sigor@sysoev.ru 1093964Sigor@sysoev.ru match++; 10941058Sigor@sysoev.ru } 1095964Sigor@sysoev.ru } 1096964Sigor@sysoev.ru 1097964Sigor@sysoev.ru 1098964Sigor@sysoev.ru void 10991264Sigor@sysoev.ru nxt_http_action_cleanup(nxt_task_t *task, nxt_http_action_t *action) 1100964Sigor@sysoev.ru { 11011264Sigor@sysoev.ru if (action->handler == nxt_http_application_handler) { 11021264Sigor@sysoev.ru nxt_router_app_use(task, action->u.application, -1); 1103964Sigor@sysoev.ru } 1104964Sigor@sysoev.ru } 1105964Sigor@sysoev.ru 1106964Sigor@sysoev.ru 11071264Sigor@sysoev.ru static nxt_http_action_t * 11081264Sigor@sysoev.ru nxt_http_route_handler(nxt_task_t *task, nxt_http_request_t *r, 11091264Sigor@sysoev.ru nxt_http_action_t *start) 1110964Sigor@sysoev.ru { 1111964Sigor@sysoev.ru nxt_http_route_t *route; 11121264Sigor@sysoev.ru nxt_http_action_t *action; 11131033Svbart@nginx.com nxt_http_route_match_t **match, **end; 1114964Sigor@sysoev.ru 1115964Sigor@sysoev.ru route = start->u.route; 1116964Sigor@sysoev.ru match = &route->match[0]; 11171033Svbart@nginx.com end = match + route->items; 1118964Sigor@sysoev.ru 11191033Svbart@nginx.com while (match < end) { 11201264Sigor@sysoev.ru action = nxt_http_route_match(r, *match); 11211264Sigor@sysoev.ru if (action != NULL) { 11221264Sigor@sysoev.ru return action; 1123964Sigor@sysoev.ru } 1124964Sigor@sysoev.ru 1125964Sigor@sysoev.ru match++; 1126964Sigor@sysoev.ru } 1127964Sigor@sysoev.ru 1128964Sigor@sysoev.ru nxt_http_request_error(task, r, NXT_HTTP_NOT_FOUND); 1129964Sigor@sysoev.ru 1130964Sigor@sysoev.ru return NULL; 1131964Sigor@sysoev.ru } 1132964Sigor@sysoev.ru 1133964Sigor@sysoev.ru 11341264Sigor@sysoev.ru static nxt_http_action_t * 1135964Sigor@sysoev.ru nxt_http_route_match(nxt_http_request_t *r, nxt_http_route_match_t *match) 1136964Sigor@sysoev.ru { 11371060Sigor@sysoev.ru nxt_int_t ret; 11381059Sigor@sysoev.ru nxt_http_route_test_t *test, *end; 11391059Sigor@sysoev.ru 11401059Sigor@sysoev.ru test = &match->test[0]; 11411059Sigor@sysoev.ru end = test + match->items; 1142964Sigor@sysoev.ru 11431059Sigor@sysoev.ru while (test < end) { 11441059Sigor@sysoev.ru if (test->rule->object != NXT_HTTP_ROUTE_TABLE) { 11451059Sigor@sysoev.ru ret = nxt_http_route_rule(r, test->rule); 1146964Sigor@sysoev.ru 11471059Sigor@sysoev.ru } else { 11481059Sigor@sysoev.ru ret = nxt_http_route_table(r, test->table); 11491059Sigor@sysoev.ru } 11501059Sigor@sysoev.ru 11511060Sigor@sysoev.ru if (ret <= 0) { 11521264Sigor@sysoev.ru /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ 11531264Sigor@sysoev.ru return (nxt_http_action_t *) (intptr_t) ret; 1154964Sigor@sysoev.ru } 1155964Sigor@sysoev.ru 11561059Sigor@sysoev.ru test++; 1157964Sigor@sysoev.ru } 1158964Sigor@sysoev.ru 11591264Sigor@sysoev.ru return &match->action; 1160964Sigor@sysoev.ru } 1161964Sigor@sysoev.ru 1162964Sigor@sysoev.ru 11631060Sigor@sysoev.ru static nxt_int_t 11641059Sigor@sysoev.ru nxt_http_route_table(nxt_http_request_t *r, nxt_http_route_table_t *table) 1165964Sigor@sysoev.ru { 11661060Sigor@sysoev.ru nxt_int_t ret; 11671059Sigor@sysoev.ru nxt_http_route_ruleset_t **ruleset, **end; 11681059Sigor@sysoev.ru 11691059Sigor@sysoev.ru ret = 1; 11701059Sigor@sysoev.ru ruleset = &table->ruleset[0]; 11711059Sigor@sysoev.ru end = ruleset + table->items; 11721059Sigor@sysoev.ru 11731059Sigor@sysoev.ru while (ruleset < end) { 11741059Sigor@sysoev.ru ret = nxt_http_route_ruleset(r, *ruleset); 11751059Sigor@sysoev.ru 11761060Sigor@sysoev.ru if (ret != 0) { 11771059Sigor@sysoev.ru return ret; 11781059Sigor@sysoev.ru } 1179964Sigor@sysoev.ru 11801059Sigor@sysoev.ru ruleset++; 11811059Sigor@sysoev.ru } 11821059Sigor@sysoev.ru 11831059Sigor@sysoev.ru return ret; 11841059Sigor@sysoev.ru } 11851059Sigor@sysoev.ru 1186964Sigor@sysoev.ru 11871060Sigor@sysoev.ru static nxt_int_t 11881059Sigor@sysoev.ru nxt_http_route_ruleset(nxt_http_request_t *r, nxt_http_route_ruleset_t *ruleset) 11891059Sigor@sysoev.ru { 11901060Sigor@sysoev.ru nxt_int_t ret; 11911059Sigor@sysoev.ru nxt_http_route_rule_t **rule, **end; 1192964Sigor@sysoev.ru 11931059Sigor@sysoev.ru rule = &ruleset->rule[0]; 11941059Sigor@sysoev.ru end = rule + ruleset->items; 1195964Sigor@sysoev.ru 11961059Sigor@sysoev.ru while (rule < end) { 11971060Sigor@sysoev.ru ret = nxt_http_route_rule(r, *rule); 11981060Sigor@sysoev.ru 11991060Sigor@sysoev.ru if (ret <= 0) { 12001060Sigor@sysoev.ru return ret; 1201964Sigor@sysoev.ru } 1202964Sigor@sysoev.ru 12031059Sigor@sysoev.ru rule++; 12041059Sigor@sysoev.ru } 12051059Sigor@sysoev.ru 12061059Sigor@sysoev.ru return 1; 12071059Sigor@sysoev.ru } 12081059Sigor@sysoev.ru 1209964Sigor@sysoev.ru 12101060Sigor@sysoev.ru static nxt_int_t 12111059Sigor@sysoev.ru nxt_http_route_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 12121059Sigor@sysoev.ru { 12131059Sigor@sysoev.ru void *p, **pp; 12141059Sigor@sysoev.ru u_char *start; 12151059Sigor@sysoev.ru size_t length; 12161059Sigor@sysoev.ru nxt_str_t *s; 12171059Sigor@sysoev.ru 12181059Sigor@sysoev.ru switch (rule->object) { 12191059Sigor@sysoev.ru 12201059Sigor@sysoev.ru case NXT_HTTP_ROUTE_HEADER: 12211059Sigor@sysoev.ru return nxt_http_route_header(r, rule); 1222964Sigor@sysoev.ru 12231059Sigor@sysoev.ru case NXT_HTTP_ROUTE_ARGUMENT: 12241061Sigor@sysoev.ru return nxt_http_route_arguments(r, rule); 1225964Sigor@sysoev.ru 12261059Sigor@sysoev.ru case NXT_HTTP_ROUTE_COOKIE: 12271062Sigor@sysoev.ru return nxt_http_route_cookies(r, rule); 12281059Sigor@sysoev.ru 12291110Saxel.duch@nginx.com case NXT_HTTP_ROUTE_SCHEME: 12301110Saxel.duch@nginx.com return nxt_http_route_scheme(r, rule); 12311110Saxel.duch@nginx.com 12321059Sigor@sysoev.ru default: 12331059Sigor@sysoev.ru break; 12341059Sigor@sysoev.ru } 1235964Sigor@sysoev.ru 12361059Sigor@sysoev.ru p = nxt_pointer_to(r, rule->u.offset); 12371059Sigor@sysoev.ru 12381059Sigor@sysoev.ru if (rule->object == NXT_HTTP_ROUTE_STRING) { 12391059Sigor@sysoev.ru s = p; 1240964Sigor@sysoev.ru 12411059Sigor@sysoev.ru } else { 12421059Sigor@sysoev.ru /* NXT_HTTP_ROUTE_STRING_PTR */ 12431059Sigor@sysoev.ru pp = p; 12441059Sigor@sysoev.ru s = *pp; 1245964Sigor@sysoev.ru 12461059Sigor@sysoev.ru if (s == NULL) { 1247964Sigor@sysoev.ru return 0; 1248964Sigor@sysoev.ru } 1249964Sigor@sysoev.ru } 1250964Sigor@sysoev.ru 12511059Sigor@sysoev.ru length = s->length; 12521059Sigor@sysoev.ru start = s->start; 12531059Sigor@sysoev.ru 12541059Sigor@sysoev.ru return nxt_http_route_test_rule(r, rule, start, length); 12551059Sigor@sysoev.ru } 12561059Sigor@sysoev.ru 12571059Sigor@sysoev.ru 12581060Sigor@sysoev.ru static nxt_int_t 12591059Sigor@sysoev.ru nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 12601059Sigor@sysoev.ru { 12611060Sigor@sysoev.ru nxt_int_t ret; 12621059Sigor@sysoev.ru nxt_http_field_t *f; 12631059Sigor@sysoev.ru 12641059Sigor@sysoev.ru ret = 0; 12651059Sigor@sysoev.ru 12661059Sigor@sysoev.ru nxt_list_each(f, r->fields) { 12671059Sigor@sysoev.ru 12681059Sigor@sysoev.ru if (rule->u.name.hash != f->hash 12691059Sigor@sysoev.ru || rule->u.name.length != f->name_length 12701059Sigor@sysoev.ru || nxt_strncasecmp(rule->u.name.start, f->name, f->name_length) 12711059Sigor@sysoev.ru != 0) 12721059Sigor@sysoev.ru { 12731059Sigor@sysoev.ru continue; 12741059Sigor@sysoev.ru } 12751059Sigor@sysoev.ru 12761059Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, f->value, f->value_length); 12771059Sigor@sysoev.ru 12781060Sigor@sysoev.ru if (ret == 0) { 12791059Sigor@sysoev.ru return ret; 12801059Sigor@sysoev.ru } 12811059Sigor@sysoev.ru 12821059Sigor@sysoev.ru } nxt_list_loop; 12831059Sigor@sysoev.ru 12841059Sigor@sysoev.ru return ret; 12851059Sigor@sysoev.ru } 12861059Sigor@sysoev.ru 12871059Sigor@sysoev.ru 12881060Sigor@sysoev.ru static nxt_int_t 12891061Sigor@sysoev.ru nxt_http_route_arguments(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 12901061Sigor@sysoev.ru { 12911061Sigor@sysoev.ru nxt_array_t *arguments; 12921061Sigor@sysoev.ru 12931061Sigor@sysoev.ru if (r->args == NULL) { 12941061Sigor@sysoev.ru return 0; 12951061Sigor@sysoev.ru } 12961061Sigor@sysoev.ru 12971061Sigor@sysoev.ru arguments = nxt_http_route_arguments_parse(r); 12981061Sigor@sysoev.ru if (nxt_slow_path(arguments == NULL)) { 12991061Sigor@sysoev.ru return -1; 13001061Sigor@sysoev.ru } 13011061Sigor@sysoev.ru 13021061Sigor@sysoev.ru return nxt_http_route_test_argument(r, rule, arguments); 13031061Sigor@sysoev.ru } 13041061Sigor@sysoev.ru 13051061Sigor@sysoev.ru 13061061Sigor@sysoev.ru static nxt_array_t * 13071061Sigor@sysoev.ru nxt_http_route_arguments_parse(nxt_http_request_t *r) 13081061Sigor@sysoev.ru { 13091061Sigor@sysoev.ru size_t name_length; 13101061Sigor@sysoev.ru u_char c, *p, *start, *end, *name; 13111061Sigor@sysoev.ru uint32_t hash; 13121061Sigor@sysoev.ru nxt_bool_t valid; 13131061Sigor@sysoev.ru nxt_array_t *args; 13141061Sigor@sysoev.ru nxt_http_name_value_t *nv; 13151061Sigor@sysoev.ru 13161061Sigor@sysoev.ru if (r->arguments != NULL) { 13171061Sigor@sysoev.ru return r->arguments; 13181061Sigor@sysoev.ru } 13191061Sigor@sysoev.ru 13201061Sigor@sysoev.ru args = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 13211061Sigor@sysoev.ru if (nxt_slow_path(args == NULL)) { 13221061Sigor@sysoev.ru return NULL; 13231061Sigor@sysoev.ru } 13241061Sigor@sysoev.ru 13251061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 13261061Sigor@sysoev.ru valid = 1; 13271061Sigor@sysoev.ru name = NULL; 13281061Sigor@sysoev.ru name_length = 0; 13291061Sigor@sysoev.ru 13301061Sigor@sysoev.ru start = r->args->start; 13311061Sigor@sysoev.ru end = start + r->args->length; 13321061Sigor@sysoev.ru 13331061Sigor@sysoev.ru for (p = start; p < end; p++) { 13341061Sigor@sysoev.ru c = *p; 13351061Sigor@sysoev.ru 13361061Sigor@sysoev.ru if (c == '=') { 13371061Sigor@sysoev.ru name_length = p - start; 13381061Sigor@sysoev.ru name = start; 13391061Sigor@sysoev.ru start = p + 1; 13401061Sigor@sysoev.ru valid = (name_length != 0); 13411061Sigor@sysoev.ru 13421061Sigor@sysoev.ru } else if (c == '&') { 13431061Sigor@sysoev.ru if (valid) { 13441061Sigor@sysoev.ru nv = nxt_http_route_argument(args, name, name_length, hash, 13451061Sigor@sysoev.ru start, p); 13461061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 13471061Sigor@sysoev.ru return NULL; 13481061Sigor@sysoev.ru } 13491061Sigor@sysoev.ru } 13501061Sigor@sysoev.ru 13511061Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 13521061Sigor@sysoev.ru valid = 1; 13531061Sigor@sysoev.ru name = NULL; 13541061Sigor@sysoev.ru start = p + 1; 13551061Sigor@sysoev.ru 13561061Sigor@sysoev.ru } else if (name == NULL) { 13571061Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 13581061Sigor@sysoev.ru } 13591061Sigor@sysoev.ru } 13601061Sigor@sysoev.ru 13611061Sigor@sysoev.ru if (valid) { 13621061Sigor@sysoev.ru nv = nxt_http_route_argument(args, name, name_length, hash, start, p); 13631061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 13641061Sigor@sysoev.ru return NULL; 13651061Sigor@sysoev.ru } 13661061Sigor@sysoev.ru } 13671061Sigor@sysoev.ru 13681061Sigor@sysoev.ru r->arguments = args; 13691061Sigor@sysoev.ru 13701061Sigor@sysoev.ru return args; 13711061Sigor@sysoev.ru } 13721061Sigor@sysoev.ru 13731061Sigor@sysoev.ru 13741061Sigor@sysoev.ru static nxt_http_name_value_t * 13751061Sigor@sysoev.ru nxt_http_route_argument(nxt_array_t *array, u_char *name, size_t name_length, 13761061Sigor@sysoev.ru uint32_t hash, u_char *start, u_char *end) 13771061Sigor@sysoev.ru { 13781061Sigor@sysoev.ru size_t length; 13791061Sigor@sysoev.ru nxt_http_name_value_t *nv; 13801061Sigor@sysoev.ru 13811061Sigor@sysoev.ru nv = nxt_array_add(array); 13821061Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 13831061Sigor@sysoev.ru return NULL; 13841061Sigor@sysoev.ru } 13851061Sigor@sysoev.ru 13861061Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 13871061Sigor@sysoev.ru 13881061Sigor@sysoev.ru length = end - start; 13891061Sigor@sysoev.ru 13901061Sigor@sysoev.ru if (name == NULL) { 13911061Sigor@sysoev.ru name_length = length; 13921061Sigor@sysoev.ru name = start; 13931061Sigor@sysoev.ru length = 0; 13941061Sigor@sysoev.ru } 13951061Sigor@sysoev.ru 13961061Sigor@sysoev.ru nv->name_length = name_length; 13971061Sigor@sysoev.ru nv->value_length = length; 13981061Sigor@sysoev.ru nv->name = name; 13991061Sigor@sysoev.ru nv->value = start; 14001061Sigor@sysoev.ru 14011061Sigor@sysoev.ru return nv; 14021061Sigor@sysoev.ru } 14031061Sigor@sysoev.ru 14041061Sigor@sysoev.ru 14051061Sigor@sysoev.ru static nxt_int_t 14061061Sigor@sysoev.ru nxt_http_route_test_argument(nxt_http_request_t *r, 14071061Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 14081061Sigor@sysoev.ru { 14091061Sigor@sysoev.ru nxt_bool_t ret; 14101061Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 14111061Sigor@sysoev.ru 14121061Sigor@sysoev.ru ret = 0; 14131061Sigor@sysoev.ru 14141061Sigor@sysoev.ru nv = array->elts; 14151061Sigor@sysoev.ru end = nv + array->nelts; 14161061Sigor@sysoev.ru 14171061Sigor@sysoev.ru while (nv < end) { 14181061Sigor@sysoev.ru 14191061Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 14201061Sigor@sysoev.ru && rule->u.name.length == nv->name_length 14211061Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 14221061Sigor@sysoev.ru { 14231061Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 14241061Sigor@sysoev.ru nv->value_length); 14251061Sigor@sysoev.ru if (ret == 0) { 14261061Sigor@sysoev.ru break; 14271061Sigor@sysoev.ru } 14281061Sigor@sysoev.ru } 14291061Sigor@sysoev.ru 14301061Sigor@sysoev.ru nv++; 14311061Sigor@sysoev.ru } 14321061Sigor@sysoev.ru 14331061Sigor@sysoev.ru return ret; 14341061Sigor@sysoev.ru } 14351061Sigor@sysoev.ru 14361061Sigor@sysoev.ru 14371061Sigor@sysoev.ru static nxt_int_t 14381110Saxel.duch@nginx.com nxt_http_route_scheme(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 14391110Saxel.duch@nginx.com { 14401110Saxel.duch@nginx.com nxt_bool_t tls, https; 14411110Saxel.duch@nginx.com 14421110Saxel.duch@nginx.com https = (rule->pattern[0].length1 == nxt_length("https")); 14431110Saxel.duch@nginx.com tls = (r->tls != NULL); 14441110Saxel.duch@nginx.com 14451110Saxel.duch@nginx.com return (tls == https); 14461110Saxel.duch@nginx.com } 14471110Saxel.duch@nginx.com 14481110Saxel.duch@nginx.com 14491110Saxel.duch@nginx.com static nxt_int_t 14501062Sigor@sysoev.ru nxt_http_route_cookies(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 14511062Sigor@sysoev.ru { 14521062Sigor@sysoev.ru nxt_array_t *cookies; 14531062Sigor@sysoev.ru 14541062Sigor@sysoev.ru cookies = nxt_http_route_cookies_parse(r); 14551062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 14561062Sigor@sysoev.ru return -1; 14571062Sigor@sysoev.ru } 14581062Sigor@sysoev.ru 14591062Sigor@sysoev.ru return nxt_http_route_test_cookie(r, rule, cookies); 14601062Sigor@sysoev.ru } 14611062Sigor@sysoev.ru 14621062Sigor@sysoev.ru 14631062Sigor@sysoev.ru static nxt_array_t * 14641062Sigor@sysoev.ru nxt_http_route_cookies_parse(nxt_http_request_t *r) 14651062Sigor@sysoev.ru { 14661062Sigor@sysoev.ru nxt_int_t ret; 14671062Sigor@sysoev.ru nxt_array_t *cookies; 14681062Sigor@sysoev.ru nxt_http_field_t *f; 14691062Sigor@sysoev.ru 14701062Sigor@sysoev.ru if (r->cookies != NULL) { 14711062Sigor@sysoev.ru return r->cookies; 14721062Sigor@sysoev.ru } 14731062Sigor@sysoev.ru 14741062Sigor@sysoev.ru cookies = nxt_array_create(r->mem_pool, 2, sizeof(nxt_http_name_value_t)); 14751062Sigor@sysoev.ru if (nxt_slow_path(cookies == NULL)) { 14761062Sigor@sysoev.ru return NULL; 14771062Sigor@sysoev.ru } 14781062Sigor@sysoev.ru 14791062Sigor@sysoev.ru nxt_list_each(f, r->fields) { 14801062Sigor@sysoev.ru 14811062Sigor@sysoev.ru if (f->hash != NJS_COOKIE_HASH 14821062Sigor@sysoev.ru || f->name_length != 6 14831062Sigor@sysoev.ru || nxt_strncasecmp(f->name, (u_char *) "Cookie", 6) != 0) 14841062Sigor@sysoev.ru { 14851062Sigor@sysoev.ru continue; 14861062Sigor@sysoev.ru } 14871062Sigor@sysoev.ru 14881062Sigor@sysoev.ru ret = nxt_http_route_cookie_parse(cookies, f->value, 14891062Sigor@sysoev.ru f->value + f->value_length); 14901062Sigor@sysoev.ru if (ret != NXT_OK) { 14911062Sigor@sysoev.ru return NULL; 14921062Sigor@sysoev.ru } 14931062Sigor@sysoev.ru 14941062Sigor@sysoev.ru } nxt_list_loop; 14951062Sigor@sysoev.ru 14961062Sigor@sysoev.ru r->cookies = cookies; 14971062Sigor@sysoev.ru 14981062Sigor@sysoev.ru return cookies; 14991062Sigor@sysoev.ru } 15001062Sigor@sysoev.ru 15011062Sigor@sysoev.ru 15021062Sigor@sysoev.ru static nxt_int_t 15031062Sigor@sysoev.ru nxt_http_route_cookie_parse(nxt_array_t *cookies, u_char *start, u_char *end) 15041062Sigor@sysoev.ru { 15051062Sigor@sysoev.ru size_t name_length; 15061062Sigor@sysoev.ru u_char c, *p, *name; 15071062Sigor@sysoev.ru nxt_http_name_value_t *nv; 15081062Sigor@sysoev.ru 15091062Sigor@sysoev.ru name = NULL; 15101062Sigor@sysoev.ru name_length = 0; 15111062Sigor@sysoev.ru 15121062Sigor@sysoev.ru for (p = start; p < end; p++) { 15131062Sigor@sysoev.ru c = *p; 15141062Sigor@sysoev.ru 15151062Sigor@sysoev.ru if (c == '=') { 15161062Sigor@sysoev.ru while (start[0] == ' ') { start++; } 15171062Sigor@sysoev.ru 15181062Sigor@sysoev.ru name_length = p - start; 15191062Sigor@sysoev.ru 15201062Sigor@sysoev.ru if (name_length != 0) { 15211062Sigor@sysoev.ru name = start; 15221062Sigor@sysoev.ru } 15231062Sigor@sysoev.ru 15241062Sigor@sysoev.ru start = p + 1; 15251062Sigor@sysoev.ru 15261062Sigor@sysoev.ru } else if (c == ';') { 15271062Sigor@sysoev.ru if (name != NULL) { 15281062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, 15291062Sigor@sysoev.ru start, p); 15301062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 15311062Sigor@sysoev.ru return NXT_ERROR; 15321062Sigor@sysoev.ru } 15331062Sigor@sysoev.ru } 15341062Sigor@sysoev.ru 15351062Sigor@sysoev.ru name = NULL; 15361062Sigor@sysoev.ru start = p + 1; 15371062Sigor@sysoev.ru } 15381062Sigor@sysoev.ru } 15391062Sigor@sysoev.ru 15401062Sigor@sysoev.ru if (name != NULL) { 15411062Sigor@sysoev.ru nv = nxt_http_route_cookie(cookies, name, name_length, start, p); 15421062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 15431062Sigor@sysoev.ru return NXT_ERROR; 15441062Sigor@sysoev.ru } 15451062Sigor@sysoev.ru } 15461062Sigor@sysoev.ru 15471062Sigor@sysoev.ru return NXT_OK; 15481062Sigor@sysoev.ru } 15491062Sigor@sysoev.ru 15501062Sigor@sysoev.ru 15511062Sigor@sysoev.ru static nxt_http_name_value_t * 15521062Sigor@sysoev.ru nxt_http_route_cookie(nxt_array_t *array, u_char *name, size_t name_length, 15531062Sigor@sysoev.ru u_char *start, u_char *end) 15541062Sigor@sysoev.ru { 15551062Sigor@sysoev.ru u_char c, *p; 15561062Sigor@sysoev.ru uint32_t hash; 15571062Sigor@sysoev.ru nxt_http_name_value_t *nv; 15581062Sigor@sysoev.ru 15591062Sigor@sysoev.ru nv = nxt_array_add(array); 15601062Sigor@sysoev.ru if (nxt_slow_path(nv == NULL)) { 15611062Sigor@sysoev.ru return NULL; 15621062Sigor@sysoev.ru } 15631062Sigor@sysoev.ru 15641062Sigor@sysoev.ru nv->name_length = name_length; 15651062Sigor@sysoev.ru nv->name = name; 15661062Sigor@sysoev.ru 15671062Sigor@sysoev.ru hash = NXT_HTTP_FIELD_HASH_INIT; 15681062Sigor@sysoev.ru 15691062Sigor@sysoev.ru for (p = name; p < name + name_length; p++) { 15701062Sigor@sysoev.ru c = *p; 15711062Sigor@sysoev.ru hash = nxt_http_field_hash_char(hash, c); 15721062Sigor@sysoev.ru } 15731062Sigor@sysoev.ru 15741062Sigor@sysoev.ru nv->hash = nxt_http_field_hash_end(hash) & 0xFFFF; 15751062Sigor@sysoev.ru 15761062Sigor@sysoev.ru while (start < end && end[-1] == ' ') { end--; } 15771062Sigor@sysoev.ru 15781062Sigor@sysoev.ru nv->value_length = end - start; 15791062Sigor@sysoev.ru nv->value = start; 15801062Sigor@sysoev.ru 15811062Sigor@sysoev.ru return nv; 15821062Sigor@sysoev.ru } 15831062Sigor@sysoev.ru 15841062Sigor@sysoev.ru 15851062Sigor@sysoev.ru static nxt_int_t 15861062Sigor@sysoev.ru nxt_http_route_test_cookie(nxt_http_request_t *r, 15871062Sigor@sysoev.ru nxt_http_route_rule_t *rule, nxt_array_t *array) 15881062Sigor@sysoev.ru { 15891062Sigor@sysoev.ru nxt_bool_t ret; 15901062Sigor@sysoev.ru nxt_http_name_value_t *nv, *end; 15911062Sigor@sysoev.ru 15921062Sigor@sysoev.ru ret = 0; 15931062Sigor@sysoev.ru 15941062Sigor@sysoev.ru nv = array->elts; 15951062Sigor@sysoev.ru end = nv + array->nelts; 15961062Sigor@sysoev.ru 15971062Sigor@sysoev.ru while (nv < end) { 15981062Sigor@sysoev.ru 15991062Sigor@sysoev.ru if (rule->u.name.hash == nv->hash 16001062Sigor@sysoev.ru && rule->u.name.length == nv->name_length 16011079Sigor@sysoev.ru && nxt_memcmp(rule->u.name.start, nv->name, nv->name_length) == 0) 16021062Sigor@sysoev.ru { 16031062Sigor@sysoev.ru ret = nxt_http_route_test_rule(r, rule, nv->value, 16041062Sigor@sysoev.ru nv->value_length); 16051062Sigor@sysoev.ru if (ret == 0) { 16061062Sigor@sysoev.ru break; 16071062Sigor@sysoev.ru } 16081062Sigor@sysoev.ru } 16091062Sigor@sysoev.ru 16101062Sigor@sysoev.ru nv++; 16111062Sigor@sysoev.ru } 16121062Sigor@sysoev.ru 16131062Sigor@sysoev.ru return ret; 16141062Sigor@sysoev.ru } 16151062Sigor@sysoev.ru 16161062Sigor@sysoev.ru 16171062Sigor@sysoev.ru static nxt_int_t 16181059Sigor@sysoev.ru nxt_http_route_test_rule(nxt_http_request_t *r, nxt_http_route_rule_t *rule, 16191059Sigor@sysoev.ru u_char *start, size_t length) 16201059Sigor@sysoev.ru { 16211060Sigor@sysoev.ru nxt_int_t ret; 16221059Sigor@sysoev.ru nxt_http_route_pattern_t *pattern, *end; 16231059Sigor@sysoev.ru 16241057Sigor@sysoev.ru ret = 1; 1625964Sigor@sysoev.ru pattern = &rule->pattern[0]; 16261033Svbart@nginx.com end = pattern + rule->items; 1627964Sigor@sysoev.ru 16281057Sigor@sysoev.ru while (pattern < end) { 1629964Sigor@sysoev.ru ret = nxt_http_route_pattern(r, pattern, start, length); 1630964Sigor@sysoev.ru 16311060Sigor@sysoev.ru /* nxt_http_route_pattern() returns either 1 or 0. */ 1632964Sigor@sysoev.ru ret ^= pattern->negative; 1633964Sigor@sysoev.ru 1634964Sigor@sysoev.ru if (pattern->any == ret) { 1635964Sigor@sysoev.ru return ret; 1636964Sigor@sysoev.ru } 1637964Sigor@sysoev.ru 1638964Sigor@sysoev.ru pattern++; 16391057Sigor@sysoev.ru } 1640964Sigor@sysoev.ru 1641964Sigor@sysoev.ru return ret; 1642964Sigor@sysoev.ru } 1643964Sigor@sysoev.ru 1644964Sigor@sysoev.ru 16451060Sigor@sysoev.ru static nxt_int_t 1646964Sigor@sysoev.ru nxt_http_route_pattern(nxt_http_request_t *r, nxt_http_route_pattern_t *pattern, 1647964Sigor@sysoev.ru u_char *start, size_t length) 1648964Sigor@sysoev.ru { 16491060Sigor@sysoev.ru u_char *p, *end, *test; 16501060Sigor@sysoev.ru size_t test_length; 16511060Sigor@sysoev.ru nxt_int_t ret; 1652964Sigor@sysoev.ru 1653964Sigor@sysoev.ru if (length < pattern->min_length) { 1654964Sigor@sysoev.ru return 0; 1655964Sigor@sysoev.ru } 1656964Sigor@sysoev.ru 16571032Sigor@sysoev.ru test = pattern->start1; 16581032Sigor@sysoev.ru test_length = pattern->length1; 1659964Sigor@sysoev.ru 1660964Sigor@sysoev.ru switch (pattern->type) { 1661964Sigor@sysoev.ru 1662964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_EXACT: 16631032Sigor@sysoev.ru if (length != test_length) { 1664964Sigor@sysoev.ru return 0; 1665964Sigor@sysoev.ru } 1666964Sigor@sysoev.ru 1667964Sigor@sysoev.ru break; 1668964Sigor@sysoev.ru 1669964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_BEGIN: 1670964Sigor@sysoev.ru break; 1671964Sigor@sysoev.ru 16721032Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_MIDDLE: 16731032Sigor@sysoev.ru ret = nxt_http_route_memcmp(start, test, test_length, 16741032Sigor@sysoev.ru pattern->case_sensitive); 16751032Sigor@sysoev.ru if (!ret) { 16761032Sigor@sysoev.ru return ret; 16771032Sigor@sysoev.ru } 16781032Sigor@sysoev.ru 16791032Sigor@sysoev.ru test = pattern->start2; 16801032Sigor@sysoev.ru test_length = pattern->length2; 16811032Sigor@sysoev.ru 16821032Sigor@sysoev.ru /* Fall through. */ 16831032Sigor@sysoev.ru 1684964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_END: 16851032Sigor@sysoev.ru start += length - test_length; 1686964Sigor@sysoev.ru break; 1687964Sigor@sysoev.ru 1688964Sigor@sysoev.ru case NXT_HTTP_ROUTE_PATTERN_SUBSTRING: 16891032Sigor@sysoev.ru end = start + length; 16901032Sigor@sysoev.ru 1691964Sigor@sysoev.ru if (pattern->case_sensitive) { 16921032Sigor@sysoev.ru p = nxt_memstrn(start, end, (char *) test, test_length); 16931032Sigor@sysoev.ru 16941032Sigor@sysoev.ru } else { 16951032Sigor@sysoev.ru p = nxt_memcasestrn(start, end, (char *) test, test_length); 1696964Sigor@sysoev.ru } 1697964Sigor@sysoev.ru 16981032Sigor@sysoev.ru return (p != NULL); 1699964Sigor@sysoev.ru } 1700964Sigor@sysoev.ru 17011032Sigor@sysoev.ru return nxt_http_route_memcmp(start, test, test_length, 17021032Sigor@sysoev.ru pattern->case_sensitive); 17031032Sigor@sysoev.ru } 17041032Sigor@sysoev.ru 17051032Sigor@sysoev.ru 17061060Sigor@sysoev.ru static nxt_int_t 17071032Sigor@sysoev.ru nxt_http_route_memcmp(u_char *start, u_char *test, size_t test_length, 17081032Sigor@sysoev.ru nxt_bool_t case_sensitive) 17091032Sigor@sysoev.ru { 17101032Sigor@sysoev.ru nxt_int_t n; 17111032Sigor@sysoev.ru 17121032Sigor@sysoev.ru if (case_sensitive) { 17131032Sigor@sysoev.ru n = nxt_memcmp(start, test, test_length); 17141032Sigor@sysoev.ru 17151032Sigor@sysoev.ru } else { 17161032Sigor@sysoev.ru n = nxt_memcasecmp(start, test, test_length); 1717964Sigor@sysoev.ru } 1718964Sigor@sysoev.ru 17191032Sigor@sysoev.ru return (n == 0); 1720964Sigor@sysoev.ru } 1721