1/* 2 * nghttp2 - HTTP/2 C Library 3 * 4 * Copyright (c) 2016 Tatsuhiro Tsujikawa 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25#include "shrpx_worker_test.h" 26 27#ifdef HAVE_UNISTD_H 28# include <unistd.h> 29#endif // HAVE_UNISTD_H 30 31#include <cstdlib> 32 33#include <CUnit/CUnit.h> 34 35#include "shrpx_worker.h" 36#include "shrpx_connect_blocker.h" 37#include "shrpx_log.h" 38 39namespace shrpx { 40 41void test_shrpx_worker_match_downstream_addr_group(void) { 42 auto groups = std::vector<std::shared_ptr<DownstreamAddrGroup>>(); 43 for (auto &s : {"nghttp2.org/", "nghttp2.org/alpha/bravo/", 44 "nghttp2.org/alpha/charlie", "nghttp2.org/delta%3A", 45 "www.nghttp2.org/", "[::1]/", "nghttp2.org/alpha/bravo/delta", 46 // Check that match is done in the single node 47 "example.com/alpha/bravo", "192.168.0.1/alpha/", "/golf/"}) { 48 auto g = std::make_shared<DownstreamAddrGroup>(); 49 g->pattern = ImmutableString(s); 50 groups.push_back(std::move(g)); 51 } 52 53 BlockAllocator balloc(1024, 1024); 54 RouterConfig routerconf; 55 56 auto &router = routerconf.router; 57 auto &wcrouter = routerconf.rev_wildcard_router; 58 auto &wp = routerconf.wildcard_patterns; 59 60 for (size_t i = 0; i < groups.size(); ++i) { 61 auto &g = groups[i]; 62 router.add_route(StringRef{g->pattern}, i); 63 } 64 65 CU_ASSERT(0 == match_downstream_addr_group( 66 routerconf, StringRef::from_lit("nghttp2.org"), 67 StringRef::from_lit("/"), groups, 255, balloc)); 68 69 // port is removed 70 CU_ASSERT(0 == match_downstream_addr_group( 71 routerconf, StringRef::from_lit("nghttp2.org:8080"), 72 StringRef::from_lit("/"), groups, 255, balloc)); 73 74 // host is case-insensitive 75 CU_ASSERT(4 == match_downstream_addr_group( 76 routerconf, StringRef::from_lit("WWW.nghttp2.org"), 77 StringRef::from_lit("/alpha"), groups, 255, balloc)); 78 79 CU_ASSERT(1 == match_downstream_addr_group( 80 routerconf, StringRef::from_lit("nghttp2.org"), 81 StringRef::from_lit("/alpha/bravo/"), groups, 255, 82 balloc)); 83 84 // /alpha/bravo also matches /alpha/bravo/ 85 CU_ASSERT(1 == match_downstream_addr_group( 86 routerconf, StringRef::from_lit("nghttp2.org"), 87 StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); 88 89 // path part is case-sensitive 90 CU_ASSERT(0 == match_downstream_addr_group( 91 routerconf, StringRef::from_lit("nghttp2.org"), 92 StringRef::from_lit("/Alpha/bravo"), groups, 255, balloc)); 93 94 CU_ASSERT(1 == match_downstream_addr_group( 95 routerconf, StringRef::from_lit("nghttp2.org"), 96 StringRef::from_lit("/alpha/bravo/charlie"), groups, 255, 97 balloc)); 98 99 CU_ASSERT(2 == match_downstream_addr_group( 100 routerconf, StringRef::from_lit("nghttp2.org"), 101 StringRef::from_lit("/alpha/charlie"), groups, 255, 102 balloc)); 103 104 // pattern which does not end with '/' must match its entirely. So 105 // this matches to group 0, not group 2. 106 CU_ASSERT(0 == match_downstream_addr_group( 107 routerconf, StringRef::from_lit("nghttp2.org"), 108 StringRef::from_lit("/alpha/charlie/"), groups, 255, 109 balloc)); 110 111 CU_ASSERT(255 == match_downstream_addr_group( 112 routerconf, StringRef::from_lit("example.org"), 113 StringRef::from_lit("/"), groups, 255, balloc)); 114 115 CU_ASSERT(255 == match_downstream_addr_group( 116 routerconf, StringRef::from_lit(""), 117 StringRef::from_lit("/"), groups, 255, balloc)); 118 119 CU_ASSERT(255 == match_downstream_addr_group( 120 routerconf, StringRef::from_lit(""), 121 StringRef::from_lit("alpha"), groups, 255, balloc)); 122 123 CU_ASSERT(255 == match_downstream_addr_group( 124 routerconf, StringRef::from_lit("foo/bar"), 125 StringRef::from_lit("/"), groups, 255, balloc)); 126 127 // If path is StringRef::from_lit("*", only match with host + "/"). 128 CU_ASSERT(0 == match_downstream_addr_group( 129 routerconf, StringRef::from_lit("nghttp2.org"), 130 StringRef::from_lit("*"), groups, 255, balloc)); 131 132 CU_ASSERT(5 == match_downstream_addr_group( 133 routerconf, StringRef::from_lit("[::1]"), 134 StringRef::from_lit("/"), groups, 255, balloc)); 135 CU_ASSERT(5 == match_downstream_addr_group( 136 routerconf, StringRef::from_lit("[::1]:8080"), 137 StringRef::from_lit("/"), groups, 255, balloc)); 138 CU_ASSERT(255 == match_downstream_addr_group( 139 routerconf, StringRef::from_lit("[::1"), 140 StringRef::from_lit("/"), groups, 255, balloc)); 141 CU_ASSERT(255 == match_downstream_addr_group( 142 routerconf, StringRef::from_lit("[::1]8000"), 143 StringRef::from_lit("/"), groups, 255, balloc)); 144 145 // Check the case where adding route extends tree 146 CU_ASSERT(6 == match_downstream_addr_group( 147 routerconf, StringRef::from_lit("nghttp2.org"), 148 StringRef::from_lit("/alpha/bravo/delta"), groups, 255, 149 balloc)); 150 151 CU_ASSERT(1 == match_downstream_addr_group( 152 routerconf, StringRef::from_lit("nghttp2.org"), 153 StringRef::from_lit("/alpha/bravo/delta/"), groups, 255, 154 balloc)); 155 156 // Check the case where query is done in a single node 157 CU_ASSERT(7 == match_downstream_addr_group( 158 routerconf, StringRef::from_lit("example.com"), 159 StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); 160 161 CU_ASSERT(255 == match_downstream_addr_group( 162 routerconf, StringRef::from_lit("example.com"), 163 StringRef::from_lit("/alpha/bravo/"), groups, 255, 164 balloc)); 165 166 CU_ASSERT(255 == match_downstream_addr_group( 167 routerconf, StringRef::from_lit("example.com"), 168 StringRef::from_lit("/alpha"), groups, 255, balloc)); 169 170 // Check the case where quey is done in a single node 171 CU_ASSERT(8 == match_downstream_addr_group( 172 routerconf, StringRef::from_lit("192.168.0.1"), 173 StringRef::from_lit("/alpha"), groups, 255, balloc)); 174 175 CU_ASSERT(8 == match_downstream_addr_group( 176 routerconf, StringRef::from_lit("192.168.0.1"), 177 StringRef::from_lit("/alpha/"), groups, 255, balloc)); 178 179 CU_ASSERT(8 == match_downstream_addr_group( 180 routerconf, StringRef::from_lit("192.168.0.1"), 181 StringRef::from_lit("/alpha/bravo"), groups, 255, balloc)); 182 183 CU_ASSERT(255 == match_downstream_addr_group( 184 routerconf, StringRef::from_lit("192.168.0.1"), 185 StringRef::from_lit("/alph"), groups, 255, balloc)); 186 187 CU_ASSERT(255 == match_downstream_addr_group( 188 routerconf, StringRef::from_lit("192.168.0.1"), 189 StringRef::from_lit("/"), groups, 255, balloc)); 190 191 // Test for wildcard hosts 192 auto g1 = std::make_shared<DownstreamAddrGroup>(); 193 g1->pattern = ImmutableString::from_lit("git.nghttp2.org"); 194 groups.push_back(std::move(g1)); 195 196 auto g2 = std::make_shared<DownstreamAddrGroup>(); 197 g2->pattern = ImmutableString::from_lit(".nghttp2.org"); 198 groups.push_back(std::move(g2)); 199 200 auto g3 = std::make_shared<DownstreamAddrGroup>(); 201 g3->pattern = ImmutableString::from_lit(".local"); 202 groups.push_back(std::move(g3)); 203 204 wp.emplace_back(StringRef::from_lit("git.nghttp2.org")); 205 wcrouter.add_route(StringRef::from_lit("gro.2ptthgn.tig"), 0); 206 wp.back().router.add_route(StringRef::from_lit("/echo/"), 10); 207 208 wp.emplace_back(StringRef::from_lit(".nghttp2.org")); 209 wcrouter.add_route(StringRef::from_lit("gro.2ptthgn."), 1); 210 wp.back().router.add_route(StringRef::from_lit("/echo/"), 11); 211 wp.back().router.add_route(StringRef::from_lit("/echo/foxtrot"), 12); 212 213 wp.emplace_back(StringRef::from_lit(".local")); 214 wcrouter.add_route(StringRef::from_lit("lacol."), 2); 215 wp.back().router.add_route(StringRef::from_lit("/"), 13); 216 217 CU_ASSERT(11 == match_downstream_addr_group( 218 routerconf, StringRef::from_lit("git.nghttp2.org"), 219 StringRef::from_lit("/echo"), groups, 255, balloc)); 220 221 CU_ASSERT(10 == match_downstream_addr_group( 222 routerconf, StringRef::from_lit("0git.nghttp2.org"), 223 StringRef::from_lit("/echo"), groups, 255, balloc)); 224 225 CU_ASSERT(11 == match_downstream_addr_group( 226 routerconf, StringRef::from_lit("it.nghttp2.org"), 227 StringRef::from_lit("/echo"), groups, 255, balloc)); 228 229 CU_ASSERT(255 == match_downstream_addr_group( 230 routerconf, StringRef::from_lit(".nghttp2.org"), 231 StringRef::from_lit("/echo/foxtrot"), groups, 255, 232 balloc)); 233 234 CU_ASSERT(9 == match_downstream_addr_group( 235 routerconf, StringRef::from_lit("alpha.nghttp2.org"), 236 StringRef::from_lit("/golf"), groups, 255, balloc)); 237 238 CU_ASSERT(0 == match_downstream_addr_group( 239 routerconf, StringRef::from_lit("nghttp2.org"), 240 StringRef::from_lit("/echo"), groups, 255, balloc)); 241 242 CU_ASSERT(13 == match_downstream_addr_group( 243 routerconf, StringRef::from_lit("test.local"), 244 StringRef{}, groups, 255, balloc)); 245} 246 247} // namespace shrpx 248