Skip to content

Commit 8e7e234

Browse files
author
Ubuntu
committed
Fixed matching for endpoint ending with '/'.
Added unit tests on http_endpoint to verify the matching logic
1 parent 36cef5b commit 8e7e234

File tree

3 files changed

+132
-29
lines changed

3 files changed

+132
-29
lines changed

src/details/http_endpoint.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,15 @@ http_endpoint::http_endpoint
5959
url_complete = url;
6060
#endif
6161

62-
if(url_complete[0] != '/')
62+
if (url_complete[url_complete.size() - 1] == '/')
63+
{
64+
url_complete = url_complete.substr(0, url_complete.size() - 1);
65+
}
66+
67+
if (url_complete[0] != '/')
68+
{
6369
url_complete = "/" + url_complete;
70+
}
6471

6572
parts = http_utils::tokenize_url(url);
6673
string buffered;
@@ -156,6 +163,7 @@ bool http_endpoint::operator <(const http_endpoint& b) const
156163

157164
bool http_endpoint::match(const http_endpoint& url) const
158165
{
166+
if (!this->reg_compiled) throw std::invalid_argument("Cannot run match. Regex suppressed.");
159167

160168
if(!this->family_url || url.url_pieces.size() < this->url_pieces.size())
161169
return regexec(&(this->re_url_normalized), url.url_complete.c_str(), 0, NULL, 0) == 0;

src/httpserver/details/http_endpoint.hpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,11 @@ class http_endpoint
132132

133133
/**
134134
* Default constructor of the class.
135-
* @param family boolean that indicates if the endpoint is a family endpoint.
136-
* A family endpoint is an endpoint that identifies a root and all its child like the same resource.
137-
* For example, if I identify "/path/" like a family endpoint and I associate to it the resource "A", also
138-
* "/path/to/res/" is automatically associated to resource "A".
139135
**/
140-
http_endpoint(bool family = false):
136+
http_endpoint():
141137
url_complete("/"),
142138
url_normalized("/"),
143-
family_url(family),
139+
family_url(false),
144140
reg_compiled(false)
145141
{
146142
}
@@ -161,7 +157,6 @@ class http_endpoint
161157
bool registration = false,
162158
bool use_regex = true
163159
);
164-
165160
private:
166161
/**
167162
* The complete url extracted

test/unit/http_endpoint_test.cpp

Lines changed: 121 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -49,22 +49,26 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_default)
4949
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), false);
5050
LT_END_AUTO_TEST(http_endpoint_default)
5151

52-
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_default_family)
53-
http_endpoint test_endpoint(true);
52+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_default)
53+
http_endpoint test_endpoint("/path/to/resource");
5454

55-
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/");
56-
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "/");
55+
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
56+
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
5757

5858
LT_CHECK_EQ(test_endpoint.get_url_pars().size(), 0);
59-
LT_CHECK_EQ(test_endpoint.get_url_pieces().size(), 0);
59+
60+
string expected_arr[] = { "path", "to", "resource" };
61+
vector<string> expected_pieces(expected_arr, expected_arr + sizeof(expected_arr) / sizeof(expected_arr[0]));
62+
LT_CHECK_COLLECTIONS_EQ(test_endpoint.get_url_pieces().begin(), test_endpoint.get_url_pieces().end(), expected_pieces.begin());
63+
6064
LT_CHECK_EQ(test_endpoint.get_chunk_positions().size(), 0);
6165

62-
LT_CHECK_EQ(test_endpoint.is_family_url(), true);
63-
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), false);
64-
LT_END_AUTO_TEST(http_endpoint_default_family)
66+
LT_CHECK_EQ(test_endpoint.is_family_url(), false);
67+
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), true);
68+
LT_END_AUTO_TEST(http_endpoint_from_string_default)
6569

66-
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_default)
67-
http_endpoint test_endpoint(std::string("/path/to/resource"));
70+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_not_beginning_with_slash)
71+
http_endpoint test_endpoint("path/to/resource");
6872

6973
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
7074
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -79,10 +83,10 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_default)
7983

8084
LT_CHECK_EQ(test_endpoint.is_family_url(), false);
8185
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), true);
82-
LT_END_AUTO_TEST(http_endpoint_from_string_default)
86+
LT_END_AUTO_TEST(http_endpoint_from_string_not_beginning_with_slash)
8387

84-
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_not_beginning_with_slash)
85-
http_endpoint test_endpoint(std::string("path/to/resource"));
88+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_ending_with_slash)
89+
http_endpoint test_endpoint("path/to/resource/");
8690

8791
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
8892
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -97,10 +101,10 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_not_beginning_
97101

98102
LT_CHECK_EQ(test_endpoint.is_family_url(), false);
99103
LT_CHECK_EQ(test_endpoint.is_regex_compiled(), true);
100-
LT_END_AUTO_TEST(http_endpoint_from_string_not_beginning_with_slash)
104+
LT_END_AUTO_TEST(http_endpoint_from_string_ending_with_slash)
101105

102106
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_family)
103-
http_endpoint test_endpoint(std::string("/path/to/resource"), true);
107+
http_endpoint test_endpoint("/path/to/resource", true);
104108

105109
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
106110
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -118,7 +122,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_family)
118122
LT_END_AUTO_TEST(http_endpoint_from_string_family)
119123

120124
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_no_regex)
121-
http_endpoint test_endpoint(std::string("/path/to/resource"), false, false, false);
125+
http_endpoint test_endpoint("/path/to/resource", false, false, false);
122126

123127
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
124128
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "/path/to/resource");
@@ -136,7 +140,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_from_string_no_regex)
136140
LT_END_AUTO_TEST(http_endpoint_from_string_no_regex)
137141

138142
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration)
139-
http_endpoint test_endpoint(std::string("/path/to/resource"), false, true);
143+
http_endpoint test_endpoint("/path/to/resource", false, true);
140144

141145
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource");
142146
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource$");
@@ -154,7 +158,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration)
154158
LT_END_AUTO_TEST(http_endpoint_registration)
155159

156160
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_nested_regex)
157-
http_endpoint test_endpoint(std::string("/path/to/resource/with/[0-9]+/to/fetch"), false, true);
161+
http_endpoint test_endpoint("/path/to/resource/with/[0-9]+/to/fetch", false, true);
158162

159163
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/[0-9]+/to/fetch");
160164
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/[0-9]+/to/fetch$");
@@ -172,7 +176,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_nested_regex)
172176
LT_END_AUTO_TEST(http_endpoint_registration_nested_regex)
173177

174178
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg)
175-
http_endpoint test_endpoint(std::string("/path/to/resource/with/{arg}/to/fetch"), false, true);
179+
http_endpoint test_endpoint("/path/to/resource/with/{arg}/to/fetch", false, true);
176180

177181
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/{arg}/to/fetch");
178182
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/([^\\/]+)/to/fetch$");
@@ -194,7 +198,7 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg)
194198
LT_END_AUTO_TEST(http_endpoint_registration_arg)
195199
196200
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg_custom_regex)
197-
http_endpoint test_endpoint(std::string("/path/to/resource/with/{arg|([0-9]+)}/to/fetch"), false, true);
201+
http_endpoint test_endpoint("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true);
198202
199203
LT_CHECK_EQ(test_endpoint.get_url_complete(), "/path/to/resource/with/{arg|([0-9]+)}/to/fetch");
200204
LT_CHECK_EQ(test_endpoint.get_url_normalized(), "^/path/to/resource/with/([0-9]+)/to/fetch$");
@@ -216,9 +220,105 @@ LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_arg_custom_re
216220
LT_END_AUTO_TEST(http_endpoint_registration_arg_custom_regex)
217221
218222
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_registration_invalid_arg)
219-
LT_CHECK_THROW(http_endpoint(std::string("/path/to/resource/with/{}/to/fetch"), false, true));
223+
LT_CHECK_THROW(http_endpoint("/path/to/resource/with/{}/to/fetch", false, true));
220224
LT_END_AUTO_TEST(http_endpoint_registration_invalid_arg)
221225
226+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_copy_constructor)
227+
http_endpoint a("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true, true);
228+
http_endpoint b(a);
229+
230+
LT_CHECK_EQ(a.get_url_complete(), b.get_url_complete());
231+
LT_CHECK_EQ(a.get_url_normalized(), b.get_url_normalized());
232+
LT_CHECK_COLLECTIONS_EQ(a.get_url_pars().begin(), a.get_url_pars().end(), b.get_url_pars().begin());
233+
LT_CHECK_COLLECTIONS_EQ(a.get_url_pieces().begin(), a.get_url_pieces().end(), b.get_url_pieces().begin());
234+
LT_CHECK_COLLECTIONS_EQ(a.get_chunk_positions().begin(), a.get_chunk_positions().end(), b.get_chunk_positions().begin());
235+
LT_CHECK_EQ(a.is_family_url(), b.is_family_url());
236+
LT_CHECK_EQ(a.is_regex_compiled(), b.is_regex_compiled());
237+
238+
LT_CHECK_EQ(a.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
239+
LT_CHECK_EQ(b.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
240+
LT_END_AUTO_TEST(http_endpoint_copy_constructor)
241+
242+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_assignment)
243+
http_endpoint a("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true, true);
244+
http_endpoint b = a;
245+
246+
LT_CHECK_EQ(a.get_url_complete(), b.get_url_complete());
247+
LT_CHECK_EQ(a.get_url_normalized(), b.get_url_normalized());
248+
LT_CHECK_COLLECTIONS_EQ(a.get_url_pars().begin(), a.get_url_pars().end(), b.get_url_pars().begin());
249+
LT_CHECK_COLLECTIONS_EQ(a.get_url_pieces().begin(), a.get_url_pieces().end(), b.get_url_pieces().begin());
250+
LT_CHECK_COLLECTIONS_EQ(a.get_chunk_positions().begin(), a.get_chunk_positions().end(), b.get_chunk_positions().begin());
251+
LT_CHECK_EQ(a.is_family_url(), b.is_family_url());
252+
LT_CHECK_EQ(a.is_regex_compiled(), b.is_regex_compiled());
253+
254+
LT_CHECK_EQ(a.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
255+
LT_CHECK_EQ(b.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
256+
LT_END_AUTO_TEST(http_endpoint_assignment)
257+
258+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex)
259+
http_endpoint test_endpoint("/path/to/resource/", false, true, true);
260+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource")), true);
261+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/")), true);
262+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to2/resource")), false);
263+
LT_END_AUTO_TEST(http_endpoint_match_regex)
264+
265+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_nested)
266+
http_endpoint test_endpoint("/path/to/resource/with/[0-9]+/to/fetch", false, true, true);
267+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/0/to/fetch")), true);
268+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
269+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource/with/1/to/fetch")), true);
270+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/1/to/fetch/")), true);
271+
LT_END_AUTO_TEST(http_endpoint_match_regex_nested)
272+
273+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_nested_capture)
274+
http_endpoint test_endpoint("/path/to/resource/with/([0-9]+)/to/fetch", false, true, true);
275+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/0/to/fetch")), true);
276+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
277+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource/with/1/to/fetch")), true);
278+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/1/to/fetch/")), true);
279+
LT_END_AUTO_TEST(http_endpoint_match_regex_nested_capture)
280+
281+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_nested_arg)
282+
http_endpoint test_endpoint("/path/to/resource/with/{arg}/to/fetch", false, true, true);
283+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/0/to/fetch")), true);
284+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
285+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource/with/1/to/fetch")), true);
286+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/1/to/fetch/")), true);
287+
LT_END_AUTO_TEST(http_endpoint_match_regex_nested_arg)
288+
289+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_nested_custom_arg)
290+
http_endpoint test_endpoint("/path/to/resource/with/{arg|([0-9]+)}/to/fetch", false, true, true);
291+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/0/to/fetch")), true);
292+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/10/to/fetch")), true);
293+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource/with/1/to/fetch")), true);
294+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/with/1/to/fetch/")), true);
295+
LT_END_AUTO_TEST(http_endpoint_match_regex_nested_custom_arg)
296+
297+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_family)
298+
http_endpoint test_endpoint("/path/to/resource", true, true, true);
299+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource")), true);
300+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/")), true);
301+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource")), true);
302+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to/resource/")), true);
303+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource")), true);
304+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("/path/to/resource/followed/by/anything")), true);
305+
306+
LT_CHECK_EQ(test_endpoint.match(http_endpoint("path/to2/resource")), false);
307+
LT_END_AUTO_TEST(http_endpoint_match_regex_family)
308+
309+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, http_endpoint_match_regex_disabled)
310+
http_endpoint test_endpoint("/path/to/resource", false, true, false);
311+
LT_CHECK_THROW(test_endpoint.match(http_endpoint("/path/to/resource")));
312+
LT_END_AUTO_TEST(http_endpoint_match_regex_disabled)
313+
314+
LT_BEGIN_AUTO_TEST(http_endpoint_suite, comparator)
315+
LT_CHECK_EQ(http_endpoint("/a/b") < http_endpoint("/a/c"), true);
316+
LT_CHECK_EQ(http_endpoint("/a/c") < http_endpoint("/a/b"), false);
317+
318+
LT_CHECK_EQ(http_endpoint("/a/b") < http_endpoint("/a/b/c"), true);
319+
LT_CHECK_EQ(http_endpoint("/a/b/c") < http_endpoint("/a/b"), false);
320+
LT_END_AUTO_TEST(comparator)
321+
222322
LT_BEGIN_AUTO_TEST_ENV()
223323
AUTORUN_TESTS()
224324
LT_END_AUTO_TEST_ENV()

0 commit comments

Comments
 (0)