diff --git a/.gitignore b/.gitignore index 3730dac..404d01d 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,8 @@ autoscan.log r3.pc stamp-h1 tests/bench_str.csv +tests/check_host config.h.in examples/simple -examples/simple_cpp \ No newline at end of file +examples/simple_cpp diff --git a/src/node.c b/src/node.c index 7ca40ba..c4d63e4 100644 --- a/src/node.c +++ b/src/node.c @@ -884,9 +884,21 @@ inline int r3_route_cmp(const R3Route *r1, const match_entry *r2) { } if ( r1->host.len && r2->host.len ) { - if (strncmp(r1->host.base, r2->host.base, r2->host.len)) { + if (r1->host.len > r2->host.len) { return -1; } + + int r1_i = r1->host.len - 1; + int r2_i = r2->host.len - 1; + for(; r1_i >= 0 ; r1_i--, r2_i--) { + if (r1_i == 0 && r1->host.base[0] == '*') { + break; + } + + if (r2->host.base[r2_i] != r1->host.base[r1_i]) { + return -1; + } + } } if (r1->remote_addr_pattern.len && r2->remote_addr.len) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f2643d7..9865ae1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -18,6 +18,7 @@ add_r3_test(check_tree check_tree.c) add_r3_test(check_slug check_slug.c) add_r3_test(check_routes check_routes.c) add_r3_test(check_str_array check_str_array.c) +add_r3_test(check_host check_host.c) add_executable(bench bench.c) target_link_libraries(bench r3) diff --git a/tests/Makefile.am b/tests/Makefile.am index 4eb40bc..5f4660b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -27,6 +27,9 @@ check_routes_SOURCES = check_routes.c TESTS += check_str_array check_str_array_SOURCES = check_str_array.c +TESTS += check_host +check_host_SOURCES = check_host.c + if ENABLE_JSON TESTS += check_json diff --git a/tests/check_host.c b/tests/check_host.c new file mode 100644 index 0000000..78d7c8d --- /dev/null +++ b/tests/check_host.c @@ -0,0 +1,91 @@ +#include "config.h" +#include +#include +#include +#include +#include "r3.h" +#include "r3_slug.h" + +START_TEST (test_hosts) +{ + R3Node * n = r3_tree_create(10); + R3Route * route = NULL; + match_entry * entry; + R3Route *matched_route; + + char * uri0 = "/foo"; + char * host0 = "foo.com"; + route = r3_tree_insert_routel(n, 0, uri0, strlen(uri0), &uri0); + route->host.base = host0; + route->host.len = strlen(host0); + + char * uri1 = "/bar"; + char * host1 = "*.bar.com"; + route = r3_tree_insert_routel(n, 0, uri1, strlen(uri1), &uri1); + route->host.base = host1; + route->host.len = strlen(host1); + + char * err = NULL; + r3_tree_compile(n, &err); + ck_assert(err == NULL); + + + entry = match_entry_create("/foo"); + entry->host.base = host0; + entry->host.len = strlen(host0); + matched_route = r3_tree_match_route(n, entry); + ck_assert(matched_route != NULL); + ck_assert(matched_route->data == &uri0); + + + entry = match_entry_create("/bar"); + entry->host.base = "www.bar.com"; + entry->host.len = strlen("www.bar.com"); + matched_route = r3_tree_match_route(n, entry); + ck_assert(matched_route != NULL); + ck_assert(matched_route->data == &uri1); + + + entry = match_entry_create("/bar"); + entry->host.base = "bar.com"; + entry->host.len = strlen("bar.com"); + matched_route = r3_tree_match_route(n, entry); + ck_assert(matched_route == NULL); + + entry = match_entry_create("/bar"); + entry->host.base = ".bar.com"; + entry->host.len = strlen(".bar.com"); + matched_route = r3_tree_match_route(n, entry); + ck_assert(matched_route == NULL); + + entry = match_entry_create("/bar"); + entry->host.base = "a.bar.com"; + entry->host.len = strlen("a.bar.com"); + matched_route = r3_tree_match_route(n, entry); + ck_assert(matched_route != NULL); + ck_assert(matched_route->data == &uri1); + + r3_tree_free(n); +} +END_TEST + + + +Suite* r3_suite (void) { + Suite *suite = suite_create("r3 host tests"); + TCase *tcase = tcase_create("testcase"); + tcase_add_test(tcase, test_hosts); + suite_add_tcase(suite, tcase); + return suite; +} + +int main (int argc, char *argv[]) { + int number_failed; + Suite *suite = r3_suite(); + SRunner *runner = srunner_create(suite); + srunner_run_all(runner, CK_NORMAL); + number_failed = srunner_ntests_failed(runner); + srunner_free(runner); + return number_failed; +} +