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 ---