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 "munitxx.h"
34
35 #include "shrpx_worker.h"
36 #include "shrpx_connect_blocker.h"
37 #include "shrpx_log.h"
38
39 namespace shrpx {
40
41 namespace {
42 const MunitTest tests[]{
43 munit_void_test(test_shrpx_worker_match_downstream_addr_group),
44 munit_test_end(),
45 };
46 } // namespace
47
48 const MunitSuite worker_suite{
49 "/worker", tests, NULL, 1, MUNIT_SUITE_OPTION_NONE,
50 };
51
test_shrpx_worker_match_downstream_addr_group(void)52 void test_shrpx_worker_match_downstream_addr_group(void) {
53 auto groups = std::vector<std::shared_ptr<DownstreamAddrGroup>>();
54 for (auto &s : {"nghttp2.org/", "nghttp2.org/alpha/bravo/",
55 "nghttp2.org/alpha/charlie", "nghttp2.org/delta%3A",
56 "www.nghttp2.org/", "[::1]/", "nghttp2.org/alpha/bravo/delta",
57 // Check that match is done in the single node
58 "example.com/alpha/bravo", "192.168.0.1/alpha/", "/golf/"}) {
59 auto g = std::make_shared<DownstreamAddrGroup>();
60 g->pattern = ImmutableString(s);
61 groups.push_back(std::move(g));
62 }
63
64 BlockAllocator balloc(1024, 1024);
65 RouterConfig routerconf;
66
67 auto &router = routerconf.router;
68 auto &wcrouter = routerconf.rev_wildcard_router;
69 auto &wp = routerconf.wildcard_patterns;
70
71 for (size_t i = 0; i < groups.size(); ++i) {
72 auto &g = groups[i];
73 router.add_route(StringRef{g->pattern}, i);
74 }
75
76 assert_size(0, ==,
77 match_downstream_addr_group(routerconf, "nghttp2.org"_sr, "/"_sr,
78 groups, 255, balloc));
79
80 // port is removed
81 assert_size(0, ==,
82 match_downstream_addr_group(routerconf, "nghttp2.org:8080"_sr,
83 "/"_sr, groups, 255, balloc));
84
85 // host is case-insensitive
86 assert_size(4, ==,
87 match_downstream_addr_group(routerconf, "WWW.nghttp2.org"_sr,
88 "/alpha"_sr, groups, 255, balloc));
89
90 assert_size(1, ==,
91 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
92 "/alpha/bravo/"_sr, groups, 255,
93 balloc));
94
95 // /alpha/bravo also matches /alpha/bravo/
96 assert_size(1, ==,
97 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
98 "/alpha/bravo"_sr, groups, 255,
99 balloc));
100
101 // path part is case-sensitive
102 assert_size(0, ==,
103 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
104 "/Alpha/bravo"_sr, groups, 255,
105 balloc));
106
107 assert_size(1, ==,
108 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
109 "/alpha/bravo/charlie"_sr, groups,
110 255, balloc));
111
112 assert_size(2, ==,
113 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
114 "/alpha/charlie"_sr, groups, 255,
115 balloc));
116
117 // pattern which does not end with '/' must match its entirely. So
118 // this matches to group 0, not group 2.
119 assert_size(0, ==,
120 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
121 "/alpha/charlie/"_sr, groups, 255,
122 balloc));
123
124 assert_size(255, ==,
125 match_downstream_addr_group(routerconf, "example.org"_sr, "/"_sr,
126 groups, 255, balloc));
127
128 assert_size(255, ==,
129 match_downstream_addr_group(routerconf, ""_sr, "/"_sr, groups,
130 255, balloc));
131
132 assert_size(255, ==,
133 match_downstream_addr_group(routerconf, ""_sr, "alpha"_sr, groups,
134 255, balloc));
135
136 assert_size(255, ==,
137 match_downstream_addr_group(routerconf, "foo/bar"_sr, "/"_sr,
138 groups, 255, balloc));
139
140 // If path is "*", only match with host + "/").
141 assert_size(0, ==,
142 match_downstream_addr_group(routerconf, "nghttp2.org"_sr, "*"_sr,
143 groups, 255, balloc));
144
145 assert_size(5, ==,
146 match_downstream_addr_group(routerconf, "[::1]"_sr, "/"_sr,
147 groups, 255, balloc));
148 assert_size(5, ==,
149 match_downstream_addr_group(routerconf, "[::1]:8080"_sr, "/"_sr,
150 groups, 255, balloc));
151 assert_size(255, ==,
152 match_downstream_addr_group(routerconf, "[::1"_sr, "/"_sr, groups,
153 255, balloc));
154 assert_size(255, ==,
155 match_downstream_addr_group(routerconf, "[::1]8000"_sr, "/"_sr,
156 groups, 255, balloc));
157
158 // Check the case where adding route extends tree
159 assert_size(6, ==,
160 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
161 "/alpha/bravo/delta"_sr, groups, 255,
162 balloc));
163
164 assert_size(1, ==,
165 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
166 "/alpha/bravo/delta/"_sr, groups, 255,
167 balloc));
168
169 // Check the case where query is done in a single node
170 assert_size(7, ==,
171 match_downstream_addr_group(routerconf, "example.com"_sr,
172 "/alpha/bravo"_sr, groups, 255,
173 balloc));
174
175 assert_size(255, ==,
176 match_downstream_addr_group(routerconf, "example.com"_sr,
177 "/alpha/bravo/"_sr, groups, 255,
178 balloc));
179
180 assert_size(255, ==,
181 match_downstream_addr_group(routerconf, "example.com"_sr,
182 "/alpha"_sr, groups, 255, balloc));
183
184 // Check the case where quey is done in a single node
185 assert_size(8, ==,
186 match_downstream_addr_group(routerconf, "192.168.0.1"_sr,
187 "/alpha"_sr, groups, 255, balloc));
188
189 assert_size(8, ==,
190 match_downstream_addr_group(routerconf, "192.168.0.1"_sr,
191 "/alpha/"_sr, groups, 255, balloc));
192
193 assert_size(8, ==,
194 match_downstream_addr_group(routerconf, "192.168.0.1"_sr,
195 "/alpha/bravo"_sr, groups, 255,
196 balloc));
197
198 assert_size(255, ==,
199 match_downstream_addr_group(routerconf, "192.168.0.1"_sr,
200 "/alph"_sr, groups, 255, balloc));
201
202 assert_size(255, ==,
203 match_downstream_addr_group(routerconf, "192.168.0.1"_sr, "/"_sr,
204 groups, 255, balloc));
205
206 // Test for wildcard hosts
207 auto g1 = std::make_shared<DownstreamAddrGroup>();
208 g1->pattern = ImmutableString::from_lit("git.nghttp2.org");
209 groups.push_back(std::move(g1));
210
211 auto g2 = std::make_shared<DownstreamAddrGroup>();
212 g2->pattern = ImmutableString::from_lit(".nghttp2.org");
213 groups.push_back(std::move(g2));
214
215 auto g3 = std::make_shared<DownstreamAddrGroup>();
216 g3->pattern = ImmutableString::from_lit(".local");
217 groups.push_back(std::move(g3));
218
219 wp.emplace_back("git.nghttp2.org"_sr);
220 wcrouter.add_route("gro.2ptthgn.tig"_sr, 0);
221 wp.back().router.add_route("/echo/"_sr, 10);
222
223 wp.emplace_back(".nghttp2.org"_sr);
224 wcrouter.add_route("gro.2ptthgn."_sr, 1);
225 wp.back().router.add_route("/echo/"_sr, 11);
226 wp.back().router.add_route("/echo/foxtrot"_sr, 12);
227
228 wp.emplace_back(".local"_sr);
229 wcrouter.add_route("lacol."_sr, 2);
230 wp.back().router.add_route("/"_sr, 13);
231
232 assert_size(11, ==,
233 match_downstream_addr_group(routerconf, "git.nghttp2.org"_sr,
234 "/echo"_sr, groups, 255, balloc));
235
236 assert_size(10, ==,
237 match_downstream_addr_group(routerconf, "0git.nghttp2.org"_sr,
238 "/echo"_sr, groups, 255, balloc));
239
240 assert_size(11, ==,
241 match_downstream_addr_group(routerconf, "it.nghttp2.org"_sr,
242 "/echo"_sr, groups, 255, balloc));
243
244 assert_size(255, ==,
245 match_downstream_addr_group(routerconf, ".nghttp2.org"_sr,
246 "/echo/foxtrot"_sr, groups, 255,
247 balloc));
248
249 assert_size(9, ==,
250 match_downstream_addr_group(routerconf, "alpha.nghttp2.org"_sr,
251 "/golf"_sr, groups, 255, balloc));
252
253 assert_size(0, ==,
254 match_downstream_addr_group(routerconf, "nghttp2.org"_sr,
255 "/echo"_sr, groups, 255, balloc));
256
257 assert_size(13, ==,
258 match_downstream_addr_group(routerconf, "test.local"_sr,
259 StringRef{}, groups, 255, balloc));
260 }
261
262 } // namespace shrpx
263