diff --git a/src/shrpx_client_handler.cc b/src/shrpx_client_handler.cc index 33cb1225..d1e4c25d 100644 --- a/src/shrpx_client_handler.cc +++ b/src/shrpx_client_handler.cc @@ -910,17 +910,19 @@ ClientHandler::get_downstream_connection(Downstream *downstream) { // have dealt with proxy case already, just use catch-all group. group_idx = catch_all; } else { + auto &balloc = downstream->get_block_allocator(); + if (!req.authority.empty()) { - group_idx = match_downstream_addr_group(routerconf, req.authority, - req.path, groups, catch_all); + group_idx = match_downstream_addr_group( + routerconf, req.authority, req.path, groups, catch_all, balloc); } else { auto h = req.fs.header(http2::HD_HOST); if (h) { group_idx = match_downstream_addr_group(routerconf, h->value, req.path, - groups, catch_all); + groups, catch_all, balloc); } else { - group_idx = match_downstream_addr_group(routerconf, StringRef{}, - req.path, groups, catch_all); + group_idx = match_downstream_addr_group( + routerconf, StringRef{}, req.path, groups, catch_all, balloc); } } } diff --git a/src/shrpx_worker.cc b/src/shrpx_worker.cc index 3e7b47df..d5c6967f 100644 --- a/src/shrpx_worker.cc +++ b/src/shrpx_worker.cc @@ -459,7 +459,7 @@ size_t match_downstream_addr_group_host( const RouterConfig &routerconf, const StringRef &host, const StringRef &path, const std::vector> &groups, - size_t catch_all) { + size_t catch_all, BlockAllocator &balloc) { const auto &router = routerconf.router; const auto &rev_wildcard_router = routerconf.rev_wildcard_router; @@ -492,12 +492,14 @@ size_t match_downstream_addr_group_host( } if (!wildcard_patterns.empty() && !host.empty()) { - auto rev_host_src = std::string{std::begin(host) + 1, std::end(host)}; - std::reverse(std::begin(rev_host_src), std::end(rev_host_src)); + auto rev_host_src = make_byte_ref(balloc, host.size() - 1); + auto ep = + std::copy(std::begin(host) + 1, std::end(host), rev_host_src.base); + std::reverse(rev_host_src.base, ep); + auto rev_host = StringRef{rev_host_src.base, ep}; ssize_t best_group = -1; const RNode *last_node = nullptr; - auto rev_host = StringRef{std::begin(rev_host_src), std::end(rev_host_src)}; for (;;) { size_t nread = 0; @@ -548,7 +550,7 @@ size_t match_downstream_addr_group( const RouterConfig &routerconf, const StringRef &hostport, const StringRef &raw_path, const std::vector> &groups, - size_t catch_all) { + size_t catch_all, BlockAllocator &balloc) { if (std::find(std::begin(hostport), std::end(hostport), '/') != std::end(hostport)) { // We use '/' specially, and if '/' is included in host, it breaks @@ -562,7 +564,7 @@ size_t match_downstream_addr_group( if (hostport.empty()) { return match_downstream_addr_group_host(routerconf, hostport, path, groups, - catch_all); + catch_all, balloc); } StringRef host; @@ -584,16 +586,17 @@ size_t match_downstream_addr_group( host = StringRef{std::begin(hostport), p}; } - std::string low_host; if (std::find_if(std::begin(host), std::end(host), [](char c) { return 'A' <= c || c <= 'Z'; }) != std::end(host)) { - low_host = host.str(); - util::inp_strlower(low_host); - host = StringRef{low_host}; + auto low_host = make_byte_ref(balloc, host.size() + 1); + auto ep = std::copy(std::begin(host), std::end(host), low_host.base); + *ep = '\0'; + util::inp_strlower(low_host.base, ep); + host = StringRef{low_host.base, ep}; } return match_downstream_addr_group_host(routerconf, host, path, groups, - catch_all); + catch_all, balloc); } void downstream_failure(DownstreamAddr *addr) { diff --git a/src/shrpx_worker.h b/src/shrpx_worker.h index 7e506029..c729af1e 100644 --- a/src/shrpx_worker.h +++ b/src/shrpx_worker.h @@ -283,7 +283,7 @@ size_t match_downstream_addr_group( const RouterConfig &routerconfig, const StringRef &hostport, const StringRef &path, const std::vector> &groups, - size_t catch_all); + size_t catch_all, BlockAllocator &balloc); void downstream_failure(DownstreamAddr *addr); diff --git a/src/shrpx_worker_test.cc b/src/shrpx_worker_test.cc index 5294433f..2e419416 100644 --- a/src/shrpx_worker_test.cc +++ b/src/shrpx_worker_test.cc @@ -49,6 +49,7 @@ void test_shrpx_worker_match_downstream_addr_group(void) { groups.push_back(std::move(g)); } + BlockAllocator balloc(1024, 1024); RouterConfig routerconf; auto &router = routerconf.router; @@ -62,122 +63,129 @@ void test_shrpx_worker_match_downstream_addr_group(void) { CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); // port is removed CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org:8080"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); // host is case-insensitive CU_ASSERT(4 == match_downstream_addr_group( routerconf, StringRef::from_lit("WWW.nghttp2.org"), - StringRef::from_lit("/alpha"), groups, 255)); + StringRef::from_lit("/alpha"), groups, 255, balloc)); CU_ASSERT(1 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/"), groups, 255)); + StringRef::from_lit("/alpha/bravo/"), groups, 255, + balloc)); // /alpha/bravo also matches /alpha/bravo/ CU_ASSERT(1 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo"), groups, 255)); + StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); // path part is case-sensitive CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/Alpha/bravo"), groups, 255)); + StringRef::from_lit("/Alpha/bravo"), groups, 255, balloc)); CU_ASSERT(1 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/charlie"), groups, 255)); + StringRef::from_lit("/alpha/bravo/charlie"), groups, 255, + balloc)); CU_ASSERT(2 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie"), groups, 255)); + StringRef::from_lit("/alpha/charlie"), groups, 255, + balloc)); // pattern which does not end with '/' must match its entirely. So // this matches to group 0, not group 2. CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/charlie/"), groups, 255)); + StringRef::from_lit("/alpha/charlie/"), groups, 255, + balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("example.org"), - StringRef::from_lit("/"), groups, 255)); - - CU_ASSERT(255 == - match_downstream_addr_group(routerconf, StringRef::from_lit(""), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit(""), - StringRef::from_lit("alpha"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); + + CU_ASSERT(255 == match_downstream_addr_group( + routerconf, StringRef::from_lit(""), + StringRef::from_lit("alpha"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("foo/bar"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); // If path is StringRef::from_lit("*", only match with host + "/"). CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("*"), groups, 255)); + StringRef::from_lit("*"), groups, 255, balloc)); - CU_ASSERT( - 5 == match_downstream_addr_group(routerconf, StringRef::from_lit("[::1]"), - StringRef::from_lit("/"), groups, 255)); + CU_ASSERT(5 == match_downstream_addr_group( + routerconf, StringRef::from_lit("[::1]"), + StringRef::from_lit("/"), groups, 255, balloc)); CU_ASSERT(5 == match_downstream_addr_group( routerconf, StringRef::from_lit("[::1]:8080"), - StringRef::from_lit("/"), groups, 255)); - CU_ASSERT(255 == - match_downstream_addr_group(routerconf, StringRef::from_lit("[::1"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); + CU_ASSERT(255 == match_downstream_addr_group( + routerconf, StringRef::from_lit("[::1"), + StringRef::from_lit("/"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("[::1]8000"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); // Check the case where adding route extends tree CU_ASSERT(6 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta"), groups, 255)); + StringRef::from_lit("/alpha/bravo/delta"), groups, 255, + balloc)); CU_ASSERT(1 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/alpha/bravo/delta/"), groups, 255)); + StringRef::from_lit("/alpha/bravo/delta/"), groups, 255, + balloc)); // Check the case where query is done in a single node CU_ASSERT(7 == match_downstream_addr_group( routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo"), groups, 255)); + StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha/bravo/"), groups, 255)); + StringRef::from_lit("/alpha/bravo/"), groups, 255, + balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("example.com"), - StringRef::from_lit("/alpha"), groups, 255)); + StringRef::from_lit("/alpha"), groups, 255, balloc)); // Check the case where quey is done in a single node CU_ASSERT(8 == match_downstream_addr_group( routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha"), groups, 255)); + StringRef::from_lit("/alpha"), groups, 255, balloc)); CU_ASSERT(8 == match_downstream_addr_group( routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/"), groups, 255)); + StringRef::from_lit("/alpha/"), groups, 255, balloc)); CU_ASSERT(8 == match_downstream_addr_group( routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alpha/bravo"), groups, 255)); + StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/alph"), groups, 255)); + StringRef::from_lit("/alph"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit("192.168.0.1"), - StringRef::from_lit("/"), groups, 255)); + StringRef::from_lit("/"), groups, 255, balloc)); // Test for wildcard hosts auto g1 = std::make_shared(); @@ -199,27 +207,28 @@ void test_shrpx_worker_match_downstream_addr_group(void) { CU_ASSERT(11 == match_downstream_addr_group( routerconf, StringRef::from_lit("git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255)); + StringRef::from_lit("/echo"), groups, 255, balloc)); CU_ASSERT(10 == match_downstream_addr_group( routerconf, StringRef::from_lit("0git.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255)); + StringRef::from_lit("/echo"), groups, 255, balloc)); CU_ASSERT(11 == match_downstream_addr_group( routerconf, StringRef::from_lit("it.nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255)); + StringRef::from_lit("/echo"), groups, 255, balloc)); CU_ASSERT(255 == match_downstream_addr_group( routerconf, StringRef::from_lit(".nghttp2.org"), - StringRef::from_lit("/echo/foxtrot"), groups, 255)); + StringRef::from_lit("/echo/foxtrot"), groups, 255, + balloc)); CU_ASSERT(9 == match_downstream_addr_group( routerconf, StringRef::from_lit("alpha.nghttp2.org"), - StringRef::from_lit("/golf"), groups, 255)); + StringRef::from_lit("/golf"), groups, 255, balloc)); CU_ASSERT(0 == match_downstream_addr_group( routerconf, StringRef::from_lit("nghttp2.org"), - StringRef::from_lit("/echo"), groups, 255)); + StringRef::from_lit("/echo"), groups, 255, balloc)); } } // namespace shrpx