Deleted
Added
nxt_http_route.c (1270:9efa309be18b) | nxt_http_route.c (1324:73562b05bf48) |
---|---|
1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_router.h> 8#include <nxt_http.h> | 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_router.h> 8#include <nxt_http.h> |
9#include <nxt_sockaddr.h> 10#include <nxt_http_route_addr.h> |
|
9 10 11typedef enum { 12 NXT_HTTP_ROUTE_TABLE = 0, 13 NXT_HTTP_ROUTE_STRING, 14 NXT_HTTP_ROUTE_STRING_PTR, 15 NXT_HTTP_ROUTE_HEADER, 16 NXT_HTTP_ROUTE_ARGUMENT, 17 NXT_HTTP_ROUTE_COOKIE, 18 NXT_HTTP_ROUTE_SCHEME, | 11 12 13typedef enum { 14 NXT_HTTP_ROUTE_TABLE = 0, 15 NXT_HTTP_ROUTE_STRING, 16 NXT_HTTP_ROUTE_STRING_PTR, 17 NXT_HTTP_ROUTE_HEADER, 18 NXT_HTTP_ROUTE_ARGUMENT, 19 NXT_HTTP_ROUTE_COOKIE, 20 NXT_HTTP_ROUTE_SCHEME, |
21 NXT_HTTP_ROUTE_SOURCE, |
|
19} nxt_http_route_object_t; 20 21 22typedef enum { 23 NXT_HTTP_ROUTE_PATTERN_EXACT = 0, 24 NXT_HTTP_ROUTE_PATTERN_BEGIN, 25 NXT_HTTP_ROUTE_PATTERN_MIDDLE, 26 NXT_HTTP_ROUTE_PATTERN_END, --- 18 unchanged lines hidden (view full) --- 45typedef struct { 46 nxt_conf_value_t *host; 47 nxt_conf_value_t *uri; 48 nxt_conf_value_t *method; 49 nxt_conf_value_t *headers; 50 nxt_conf_value_t *arguments; 51 nxt_conf_value_t *cookies; 52 nxt_conf_value_t *scheme; | 22} nxt_http_route_object_t; 23 24 25typedef enum { 26 NXT_HTTP_ROUTE_PATTERN_EXACT = 0, 27 NXT_HTTP_ROUTE_PATTERN_BEGIN, 28 NXT_HTTP_ROUTE_PATTERN_MIDDLE, 29 NXT_HTTP_ROUTE_PATTERN_END, --- 18 unchanged lines hidden (view full) --- 48typedef struct { 49 nxt_conf_value_t *host; 50 nxt_conf_value_t *uri; 51 nxt_conf_value_t *method; 52 nxt_conf_value_t *headers; 53 nxt_conf_value_t *arguments; 54 nxt_conf_value_t *cookies; 55 nxt_conf_value_t *scheme; |
56 nxt_conf_value_t *source; |
|
53} nxt_http_route_match_conf_t; 54 55 56typedef struct { 57 u_char *start1; 58 u_char *start2; 59 uint32_t length1; 60 uint32_t length2; --- 52 unchanged lines hidden (view full) --- 113typedef struct { 114 /* The object must be the first field. */ 115 nxt_http_route_object_t object:8; 116 uint32_t items; 117 nxt_http_route_ruleset_t *ruleset[0]; 118} nxt_http_route_table_t; 119 120 | 57} nxt_http_route_match_conf_t; 58 59 60typedef struct { 61 u_char *start1; 62 u_char *start2; 63 uint32_t length1; 64 uint32_t length2; --- 52 unchanged lines hidden (view full) --- 117typedef struct { 118 /* The object must be the first field. */ 119 nxt_http_route_object_t object:8; 120 uint32_t items; 121 nxt_http_route_ruleset_t *ruleset[0]; 122} nxt_http_route_table_t; 123 124 |
125typedef struct { 126 /* The object must be the first field. */ 127 nxt_http_route_object_t object:8; 128 uint32_t items; 129 nxt_http_route_addr_pattern_t addr_pattern[0]; 130} nxt_http_route_addr_rule_t; 131 132 |
|
121typedef union { 122 nxt_http_route_rule_t *rule; 123 nxt_http_route_table_t *table; | 133typedef union { 134 nxt_http_route_rule_t *rule; 135 nxt_http_route_table_t *table; |
136 nxt_http_route_addr_rule_t *addr_rule; |
|
124} nxt_http_route_test_t; 125 126 127typedef struct { 128 uint32_t items; 129 nxt_http_action_t action; 130 nxt_http_route_test_t test[0]; 131} nxt_http_route_match_t; --- 33 unchanged lines hidden (view full) --- 165 nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 166 nxt_bool_t case_sensitive); 167static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, 168 nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 169 nxt_bool_t case_sensitive); 170static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, 171 nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, 172 nxt_bool_t case_sensitive); | 137} nxt_http_route_test_t; 138 139 140typedef struct { 141 uint32_t items; 142 nxt_http_action_t action; 143 nxt_http_route_test_t test[0]; 144} nxt_http_route_match_t; --- 33 unchanged lines hidden (view full) --- 178 nxt_mp_t *mp, nxt_conf_value_t *table_cv, nxt_http_route_object_t object, 179 nxt_bool_t case_sensitive); 180static nxt_http_route_ruleset_t *nxt_http_route_ruleset_create(nxt_task_t *task, 181 nxt_mp_t *mp, nxt_conf_value_t *ruleset_cv, nxt_http_route_object_t object, 182 nxt_bool_t case_sensitive); 183static nxt_http_route_rule_t *nxt_http_route_rule_name_create(nxt_task_t *task, 184 nxt_mp_t *mp, nxt_conf_value_t *rule_cv, nxt_str_t *name, 185 nxt_bool_t case_sensitive); |
186static nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create( 187 nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv); |
|
173static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, 174 nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 175 nxt_http_route_pattern_case_t pattern_case); 176static int nxt_http_pattern_compare(const void *one, const void *two); 177static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 178 nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 179 nxt_http_route_pattern_case_t pattern_case); 180static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, --- 10 unchanged lines hidden (view full) --- 191static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, 192 nxt_http_request_t *r, nxt_http_action_t *start); 193static nxt_http_action_t *nxt_http_route_match(nxt_http_request_t *r, 194 nxt_http_route_match_t *match); 195static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, 196 nxt_http_route_table_t *table); 197static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, 198 nxt_http_route_ruleset_t *ruleset); | 188static nxt_http_route_rule_t *nxt_http_route_rule_create(nxt_task_t *task, 189 nxt_mp_t *mp, nxt_conf_value_t *cv, nxt_bool_t case_sensitive, 190 nxt_http_route_pattern_case_t pattern_case); 191static int nxt_http_pattern_compare(const void *one, const void *two); 192static nxt_int_t nxt_http_route_pattern_create(nxt_task_t *task, nxt_mp_t *mp, 193 nxt_conf_value_t *cv, nxt_http_route_pattern_t *pattern, 194 nxt_http_route_pattern_case_t pattern_case); 195static u_char *nxt_http_route_pattern_copy(nxt_mp_t *mp, nxt_str_t *test, --- 10 unchanged lines hidden (view full) --- 206static nxt_http_action_t *nxt_http_route_handler(nxt_task_t *task, 207 nxt_http_request_t *r, nxt_http_action_t *start); 208static nxt_http_action_t *nxt_http_route_match(nxt_http_request_t *r, 209 nxt_http_route_match_t *match); 210static nxt_int_t nxt_http_route_table(nxt_http_request_t *r, 211 nxt_http_route_table_t *table); 212static nxt_int_t nxt_http_route_ruleset(nxt_http_request_t *r, 213 nxt_http_route_ruleset_t *ruleset); |
214static nxt_int_t nxt_http_route_addr_rule(nxt_http_request_t *r, 215 nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sockaddr); |
|
199static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, 200 nxt_http_route_rule_t *rule); 201static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, 202 nxt_http_route_rule_t *rule); 203static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, 204 nxt_http_route_rule_t *rule); 205static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); 206static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, --- 117 unchanged lines hidden (view full) --- 324 offsetof(nxt_http_route_match_conf_t, arguments), 325 }, 326 327 { 328 nxt_string("cookies"), 329 NXT_CONF_MAP_PTR, 330 offsetof(nxt_http_route_match_conf_t, cookies), 331 }, | 216static nxt_int_t nxt_http_route_rule(nxt_http_request_t *r, 217 nxt_http_route_rule_t *rule); 218static nxt_int_t nxt_http_route_header(nxt_http_request_t *r, 219 nxt_http_route_rule_t *rule); 220static nxt_int_t nxt_http_route_arguments(nxt_http_request_t *r, 221 nxt_http_route_rule_t *rule); 222static nxt_array_t *nxt_http_route_arguments_parse(nxt_http_request_t *r); 223static nxt_http_name_value_t *nxt_http_route_argument(nxt_array_t *array, --- 117 unchanged lines hidden (view full) --- 341 offsetof(nxt_http_route_match_conf_t, arguments), 342 }, 343 344 { 345 nxt_string("cookies"), 346 NXT_CONF_MAP_PTR, 347 offsetof(nxt_http_route_match_conf_t, cookies), 348 }, |
349 350 { 351 nxt_string("source"), 352 NXT_CONF_MAP_PTR, 353 offsetof(nxt_http_route_match_conf_t, source), 354 }, |
|
332}; 333 334 335static nxt_http_route_t * 336nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 337 nxt_conf_value_t *cv) 338{ 339 size_t size; --- 36 unchanged lines hidden (view full) --- 376 uint32_t n; 377 nxt_mp_t *mp; 378 nxt_int_t ret; 379 nxt_conf_value_t *match_conf; 380 nxt_http_route_test_t *test; 381 nxt_http_route_rule_t *rule; 382 nxt_http_route_table_t *table; 383 nxt_http_route_match_t *match; | 355}; 356 357 358static nxt_http_route_t * 359nxt_http_route_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, 360 nxt_conf_value_t *cv) 361{ 362 size_t size; --- 36 unchanged lines hidden (view full) --- 399 uint32_t n; 400 nxt_mp_t *mp; 401 nxt_int_t ret; 402 nxt_conf_value_t *match_conf; 403 nxt_http_route_test_t *test; 404 nxt_http_route_rule_t *rule; 405 nxt_http_route_table_t *table; 406 nxt_http_route_match_t *match; |
407 nxt_http_route_addr_rule_t *addr_rule; |
|
384 nxt_http_route_match_conf_t mtcf; 385 386 static nxt_str_t match_path = nxt_string("/match"); 387 388 match_conf = nxt_conf_get_path(cv, &match_path); 389 390 n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; 391 size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_rule_t *); --- 108 unchanged lines hidden (view full) --- 500 if (table == NULL) { 501 return NULL; 502 } 503 504 test->table = table; 505 test++; 506 } 507 | 408 nxt_http_route_match_conf_t mtcf; 409 410 static nxt_str_t match_path = nxt_string("/match"); 411 412 match_conf = nxt_conf_get_path(cv, &match_path); 413 414 n = (match_conf != NULL) ? nxt_conf_object_members_count(match_conf) : 0; 415 size = sizeof(nxt_http_route_match_t) + n * sizeof(nxt_http_route_rule_t *); --- 108 unchanged lines hidden (view full) --- 524 if (table == NULL) { 525 return NULL; 526 } 527 528 test->table = table; 529 test++; 530 } 531 |
532 if (mtcf.source != NULL) { 533 addr_rule = nxt_http_route_addr_rule_create(task, mp, mtcf.source); 534 if (addr_rule == NULL) { 535 return NULL; 536 } 537 538 addr_rule->object = NXT_HTTP_ROUTE_SOURCE; 539 test->addr_rule = addr_rule; 540 test++; 541 } 542 |
|
508 return match; 509} 510 511 512static nxt_conf_map_t nxt_http_route_action_conf[] = { 513 { 514 nxt_string("pass"), 515 NXT_CONF_MAP_PTR, --- 249 unchanged lines hidden (view full) --- 765 return NULL; 766 } 767 } 768 769 return rule; 770} 771 772 | 543 return match; 544} 545 546 547static nxt_conf_map_t nxt_http_route_action_conf[] = { 548 { 549 nxt_string("pass"), 550 NXT_CONF_MAP_PTR, --- 249 unchanged lines hidden (view full) --- 800 return NULL; 801 } 802 } 803 804 return rule; 805} 806 807 |
808static nxt_http_route_addr_rule_t * 809nxt_http_route_addr_rule_create(nxt_task_t *task, nxt_mp_t *mp, 810 nxt_conf_value_t *cv) 811{ 812 size_t size; 813 uint32_t i, n; 814 nxt_bool_t array; 815 nxt_conf_value_t *value; 816 nxt_http_route_addr_rule_t *addr_rule; 817 nxt_http_route_addr_pattern_t *pattern; 818 819 array = (nxt_conf_type(cv) == NXT_CONF_ARRAY); 820 n = array ? nxt_conf_array_elements_count(cv) : 1; 821 822 size = sizeof(nxt_http_route_addr_rule_t) 823 + n * sizeof(nxt_http_route_addr_pattern_t); 824 825 addr_rule = nxt_mp_alloc(mp, size); 826 if (nxt_slow_path(addr_rule == NULL)) { 827 return NULL; 828 } 829 830 addr_rule->items = n; 831 832 if (!array) { 833 pattern = &addr_rule->addr_pattern[0]; 834 835 if (nxt_http_route_addr_pattern_parse(mp, pattern, cv) != NXT_OK) { 836 return NULL; 837 } 838 839 return addr_rule; 840 } 841 842 for (i = 0; i < n; i++) { 843 pattern = &addr_rule->addr_pattern[i]; 844 value = nxt_conf_get_array_element(cv, i); 845 846 if (nxt_http_route_addr_pattern_parse(mp, pattern, value) != NXT_OK) { 847 return NULL; 848 } 849 } 850 851 return addr_rule; 852} 853 854 |
|
773static int 774nxt_http_pattern_compare(const void *one, const void *two) 775{ 776 nxt_str_t test; 777 nxt_bool_t negative1, negative2; 778 nxt_conf_value_t *value; 779 780 value = (nxt_conf_value_t *) one; --- 355 unchanged lines hidden (view full) --- 1136{ 1137 nxt_int_t ret; 1138 nxt_http_route_test_t *test, *end; 1139 1140 test = &match->test[0]; 1141 end = test + match->items; 1142 1143 while (test < end) { | 855static int 856nxt_http_pattern_compare(const void *one, const void *two) 857{ 858 nxt_str_t test; 859 nxt_bool_t negative1, negative2; 860 nxt_conf_value_t *value; 861 862 value = (nxt_conf_value_t *) one; --- 355 unchanged lines hidden (view full) --- 1218{ 1219 nxt_int_t ret; 1220 nxt_http_route_test_t *test, *end; 1221 1222 test = &match->test[0]; 1223 end = test + match->items; 1224 1225 while (test < end) { |
1144 if (test->rule->object != NXT_HTTP_ROUTE_TABLE) { 1145 ret = nxt_http_route_rule(r, test->rule); 1146 1147 } else { | 1226 switch (test->rule->object) { 1227 case NXT_HTTP_ROUTE_TABLE: |
1148 ret = nxt_http_route_table(r, test->table); | 1228 ret = nxt_http_route_table(r, test->table); |
1229 break; 1230 case NXT_HTTP_ROUTE_SOURCE: 1231 ret = nxt_http_route_addr_rule(r, test->addr_rule, r->remote); 1232 break; 1233 default: 1234 ret = nxt_http_route_rule(r, test->rule); 1235 break; |
|
1149 } 1150 1151 if (ret <= 0) { 1152 /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ 1153 return (nxt_http_action_t *) (intptr_t) ret; 1154 } 1155 1156 test++; --- 94 unchanged lines hidden (view full) --- 1251 length = s->length; 1252 start = s->start; 1253 1254 return nxt_http_route_test_rule(r, rule, start, length); 1255} 1256 1257 1258static nxt_int_t | 1236 } 1237 1238 if (ret <= 0) { 1239 /* 0 => NULL, -1 => NXT_HTTP_ACTION_ERROR. */ 1240 return (nxt_http_action_t *) (intptr_t) ret; 1241 } 1242 1243 test++; --- 94 unchanged lines hidden (view full) --- 1338 length = s->length; 1339 start = s->start; 1340 1341 return nxt_http_route_test_rule(r, rule, start, length); 1342} 1343 1344 1345static nxt_int_t |
1346nxt_http_route_addr_pattern_match(nxt_http_route_addr_pattern_t *p, 1347 nxt_sockaddr_t *sa) 1348{ 1349#if (NXT_INET6) 1350 uint32_t i; 1351#endif 1352 in_port_t in_port; 1353 nxt_int_t match; 1354 struct sockaddr_in *sin; 1355#if (NXT_INET6) 1356 struct sockaddr_in6 *sin6; 1357#endif 1358 nxt_http_route_addr_base_t *base; 1359 1360 base = &p->base; 1361 1362 switch (sa->u.sockaddr.sa_family) { 1363 1364 case AF_INET: 1365 1366 match = (base->addr_family == AF_INET 1367 || base->addr_family == AF_UNSPEC); 1368 if (!match) { 1369 break; 1370 } 1371 1372 sin = &sa->u.sockaddr_in; 1373 in_port = ntohs(sin->sin_port); 1374 1375 match = (in_port >= base->port.start && in_port <= base->port.end); 1376 if (!match) { 1377 break; 1378 } 1379 1380 switch (base->match_type) { 1381 1382 case NXT_HTTP_ROUTE_ADDR_ANY: 1383 break; 1384 1385 case NXT_HTTP_ROUTE_ADDR_EXACT: 1386 match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 1387 sizeof(struct in_addr)) 1388 == 0); 1389 break; 1390 1391 case NXT_HTTP_ROUTE_ADDR_RANGE: 1392 match = (nxt_memcmp(&sin->sin_addr, &p->addr.v4.start, 1393 sizeof(struct in_addr)) >= 0 1394 && nxt_memcmp(&sin->sin_addr, &p->addr.v4.end, 1395 sizeof(struct in_addr)) <= 0); 1396 break; 1397 1398 case NXT_HTTP_ROUTE_ADDR_CIDR: 1399 match = ((sin->sin_addr.s_addr & p->addr.v4.end) 1400 == p->addr.v4.start); 1401 break; 1402 1403 default: 1404 nxt_unreachable(); 1405 } 1406 1407 break; 1408 1409#if (NXT_INET6) 1410 case AF_INET6: 1411 1412 match = (base->addr_family == AF_INET6 1413 || base->addr_family == AF_UNSPEC); 1414 if (!match) { 1415 break; 1416 } 1417 1418 sin6 = &sa->u.sockaddr_in6; 1419 in_port = ntohs(sin6->sin6_port); 1420 1421 match = (in_port >= base->port.start && in_port <= base->port.end); 1422 if (!match) { 1423 break; 1424 } 1425 1426 switch (base->match_type) { 1427 1428 case NXT_HTTP_ROUTE_ADDR_ANY: 1429 break; 1430 1431 case NXT_HTTP_ROUTE_ADDR_EXACT: 1432 match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 1433 sizeof(struct in6_addr)) 1434 == 0); 1435 break; 1436 1437 case NXT_HTTP_ROUTE_ADDR_RANGE: 1438 match = (nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.start, 1439 sizeof(struct in6_addr)) >= 0 1440 && nxt_memcmp(&sin6->sin6_addr, &p->addr.v6.end, 1441 sizeof(struct in6_addr)) <= 0); 1442 break; 1443 1444 case NXT_HTTP_ROUTE_ADDR_CIDR: 1445 for (i = 0; i < 16; i++) { 1446 match = ((sin6->sin6_addr.s6_addr[i] 1447 & p->addr.v6.end.s6_addr[i]) 1448 == p->addr.v6.start.s6_addr[i]); 1449 1450 if (!match) { 1451 break; 1452 } 1453 } 1454 1455 break; 1456 1457 default: 1458 nxt_unreachable(); 1459 } 1460 1461 break; 1462#endif 1463 1464 default: 1465 match = 0; 1466 break; 1467 } 1468 1469 return match ^ base->negative; 1470} 1471 1472 1473static nxt_int_t 1474nxt_http_route_addr_rule(nxt_http_request_t *r, 1475 nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sa) 1476{ 1477 uint32_t i, n; 1478 nxt_http_route_addr_pattern_t *p; 1479 1480 n = addr_rule->items; 1481 1482 for (i = 0; i < n; i++) { 1483 p = &addr_rule->addr_pattern[i]; 1484 if (nxt_http_route_addr_pattern_match(p, sa)) { 1485 return 1; 1486 } 1487 } 1488 1489 return 0; 1490} 1491 1492 1493static nxt_int_t |
|
1259nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 1260{ 1261 nxt_int_t ret; 1262 nxt_http_field_t *f; 1263 1264 ret = 0; 1265 1266 nxt_list_each(f, r->fields) { --- 454 unchanged lines hidden --- | 1494nxt_http_route_header(nxt_http_request_t *r, nxt_http_route_rule_t *rule) 1495{ 1496 nxt_int_t ret; 1497 nxt_http_field_t *f; 1498 1499 ret = 0; 1500 1501 nxt_list_each(f, r->fields) { --- 454 unchanged lines hidden --- |