blob: cd668171db75f2ceb23e64b15e3cbf3b1fa4c7fb [file] [log] [blame]
Ed Tanouse0d918b2018-03-27 17:41:04 -07001#include "crow.h"
Ed Tanous8041f312017-04-03 09:47:01 -07002#include <iostream>
3#include <sstream>
4#include <vector>
Ed Tanous8041f312017-04-03 09:47:01 -07005#include "gtest/gtest.h"
Ed Tanous55c7b7a2018-05-22 15:27:24 -07006#undef BMCWEB_LOG_LEVEL
7#define BMCWEB_LOG_LEVEL 0
Ed Tanous8041f312017-04-03 09:47:01 -07008
9using namespace std;
10using namespace crow;
11
12bool failed__ = false;
Ed Tanous1ff48782017-04-18 12:45:08 -070013void error_print() { cerr << endl; }
14
15template <typename A, typename... Args>
16void error_print(const A& a, Args... args) {
17 cerr << a;
18 error_print(args...);
Ed Tanous8041f312017-04-03 09:47:01 -070019}
20
Ed Tanous1ff48782017-04-18 12:45:08 -070021template <typename... Args>
22void fail(Args... args) {
23 error_print(args...);
24 failed__ = true;
Ed Tanous8041f312017-04-03 09:47:01 -070025}
26
Ed Tanous1ff48782017-04-18 12:45:08 -070027#define ASSERT_EQUAL(a, b) \
28 if ((a) != (b)) \
29 fail(__FILE__ ":", __LINE__, ": Assert fail: expected ", (a), " actual ", \
30 (b), ", " #a " == " #b ", at " __FILE__ ":", __LINE__)
31#define ASSERT_NOTEQUAL(a, b) \
32 if ((a) == (b)) \
33 fail(__FILE__ ":", __LINE__, ": Assert fail: not expected ", (a), \
34 ", " #a " != " #b ", at " __FILE__ ":", __LINE__)
Ed Tanous8041f312017-04-03 09:47:01 -070035
Ed Tanous1ff48782017-04-18 12:45:08 -070036#define DISABLE_TEST(x) \
37 struct test##x { \
38 void test(); \
39 } x##_; \
40 void test##x::test()
Ed Tanous8041f312017-04-03 09:47:01 -070041
42#define LOCALHOST_ADDRESS "127.0.0.1"
43
Ed Tanous1ff48782017-04-18 12:45:08 -070044TEST(Crow, Rule) {
45 TaggedRule<> r("/http/");
46 r.name("abc");
Ed Tanous8041f312017-04-03 09:47:01 -070047
Ed Tanous1ff48782017-04-18 12:45:08 -070048 // empty handler - fail to validate
49 try {
Ed Tanous8041f312017-04-03 09:47:01 -070050 r.validate();
Ed Tanous1ff48782017-04-18 12:45:08 -070051 fail("empty handler should fail to validate");
52 } catch (runtime_error& e) {
53 }
Ed Tanous8041f312017-04-03 09:47:01 -070054
Ed Tanous1ff48782017-04-18 12:45:08 -070055 int x = 0;
56
57 // registering handler
58 r([&x] {
59 x = 1;
60 return "";
61 });
62
63 r.validate();
64
Ed Tanous55c7b7a2018-05-22 15:27:24 -070065 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -070066
67 // executing handler
68 ASSERT_EQUAL(0, x);
Ed Tanouse0d918b2018-03-27 17:41:04 -070069 boost::beast::http::request<boost::beast::http::string_body> req{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -070070 r.handle(Request(req), res, RoutingParams());
Ed Tanous1ff48782017-04-18 12:45:08 -070071 ASSERT_EQUAL(1, x);
72
Ed Tanous55c7b7a2018-05-22 15:27:24 -070073 // registering handler with Request argument
74 r([&x](const crow::Request&) {
Ed Tanous1ff48782017-04-18 12:45:08 -070075 x = 2;
76 return "";
77 });
78
79 r.validate();
80
81 // executing handler
82 ASSERT_EQUAL(1, x);
Ed Tanous55c7b7a2018-05-22 15:27:24 -070083 r.handle(Request(req), res, RoutingParams());
Ed Tanous1ff48782017-04-18 12:45:08 -070084 ASSERT_EQUAL(2, x);
85}
86
87TEST(Crow, ParameterTagging) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -070088 static_assert(black_magic::isValid("<int><int><int>"), "valid url");
89 static_assert(!black_magic::isValid("<int><int<<int>"), "invalid url");
90 static_assert(!black_magic::isValid("nt>"), "invalid url");
Ed Tanous1ff48782017-04-18 12:45:08 -070091 ASSERT_EQUAL(1, black_magic::get_parameter_tag("<int>"));
92 ASSERT_EQUAL(2, black_magic::get_parameter_tag("<uint>"));
93 ASSERT_EQUAL(3, black_magic::get_parameter_tag("<float>"));
94 ASSERT_EQUAL(3, black_magic::get_parameter_tag("<double>"));
95 ASSERT_EQUAL(4, black_magic::get_parameter_tag("<str>"));
96 ASSERT_EQUAL(4, black_magic::get_parameter_tag("<string>"));
97 ASSERT_EQUAL(5, black_magic::get_parameter_tag("<path>"));
98 ASSERT_EQUAL(6 * 6 + 6 + 1,
99 black_magic::get_parameter_tag("<int><int><int>"));
100 ASSERT_EQUAL(6 * 6 + 6 + 2,
101 black_magic::get_parameter_tag("<uint><int><int>"));
102 ASSERT_EQUAL(6 * 6 + 6 * 3 + 2,
103 black_magic::get_parameter_tag("<uint><double><int>"));
104
105 // url definition parsed in compile time, build into *one number*, and given
106 // to template argument
107 static_assert(
108 std::is_same<black_magic::S<uint64_t, double, int64_t>,
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700109 black_magic::Arguments<6 * 6 + 6 * 3 + 2>::type>::value,
Ed Tanous1ff48782017-04-18 12:45:08 -0700110 "tag to type container");
111}
112
113TEST(Crow, PathRouting) {
114 SimpleApp app;
115
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700116 BMCWEB_ROUTE(app, "/file")
Ed Tanous1ff48782017-04-18 12:45:08 -0700117 ([] { return "file"; });
118
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700119 BMCWEB_ROUTE(app, "/path/")
Ed Tanous1ff48782017-04-18 12:45:08 -0700120 ([] { return "path"; });
121
122 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700123 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700124 Request req{r};
125 Response res;
Ed Tanous8041f312017-04-03 09:47:01 -0700126
Ed Tanous1ff48782017-04-18 12:45:08 -0700127 req.url = "/file";
Ed Tanous8041f312017-04-03 09:47:01 -0700128
Ed Tanous1ff48782017-04-18 12:45:08 -0700129 app.handle(req, res);
Ed Tanous8041f312017-04-03 09:47:01 -0700130
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700131 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700132 }
133 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700134 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700135 Request req{r};
136 Response res;
Ed Tanous8041f312017-04-03 09:47:01 -0700137
Ed Tanous1ff48782017-04-18 12:45:08 -0700138 req.url = "/file/";
139
140 app.handle(req, res);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700141 ASSERT_EQUAL(404, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700142 }
143 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700144 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700145 Request req{r};
146 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700147
148 req.url = "/path";
149
150 app.handle(req, res);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700151 ASSERT_NOTEQUAL(404, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700152 }
153 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700154 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700155 Request req{r};
156 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700157
158 req.url = "/path/";
159
160 app.handle(req, res);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700161 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700162 }
Ed Tanous8041f312017-04-03 09:47:01 -0700163}
164
Ed Tanous1ff48782017-04-18 12:45:08 -0700165TEST(Crow, RoutingTest) {
166 SimpleApp app;
167 int A{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700168 uint32_t b{};
Ed Tanous1ff48782017-04-18 12:45:08 -0700169 double C{};
170 string D{};
171 string E{};
Ed Tanous8041f312017-04-03 09:47:01 -0700172
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700173 BMCWEB_ROUTE(app, "/0/<uint>")
Ed Tanous1ff48782017-04-18 12:45:08 -0700174 ([&](uint32_t b) {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700175 b = b;
Ed Tanous1ff48782017-04-18 12:45:08 -0700176 return "OK";
177 });
178
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700179 BMCWEB_ROUTE(app, "/1/<int>/<uint>")
Ed Tanous1ff48782017-04-18 12:45:08 -0700180 ([&](int a, uint32_t b) {
181 A = a;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700182 b = b;
Ed Tanous1ff48782017-04-18 12:45:08 -0700183 return "OK";
184 });
185
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700186 BMCWEB_ROUTE(app, "/4/<int>/<uint>/<double>/<string>")
Ed Tanous1ff48782017-04-18 12:45:08 -0700187 ([&](int a, uint32_t b, double c, string d) {
188 A = a;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700189 b = b;
Ed Tanous1ff48782017-04-18 12:45:08 -0700190 C = c;
191 D = d;
192 return "OK";
193 });
194
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700195 BMCWEB_ROUTE(app, "/5/<int>/<uint>/<double>/<string>/<path>")
Ed Tanous1ff48782017-04-18 12:45:08 -0700196 ([&](int a, uint32_t b, double c, string d, string e) {
197 A = a;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700198 b = b;
Ed Tanous1ff48782017-04-18 12:45:08 -0700199 C = c;
200 D = d;
201 E = e;
202 return "OK";
203 });
204
205 app.validate();
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700206 // app.debugPrint();
Ed Tanous1ff48782017-04-18 12:45:08 -0700207 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700208 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700209 Request req{r};
210 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700211
212 req.url = "/-1";
213
214 app.handle(req, res);
215
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700216 ASSERT_EQUAL(404, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700217 }
218
219 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700220 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700221 Request req{r};
222 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700223
224 req.url = "/0/1001999";
225
226 app.handle(req, res);
227
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700228 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700229
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700230 ASSERT_EQUAL(1001999, b);
Ed Tanous1ff48782017-04-18 12:45:08 -0700231 }
232
233 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700234 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700235 Request req{r};
236 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700237
238 req.url = "/1/-100/1999";
239
240 app.handle(req, res);
241
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700242 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700243
244 ASSERT_EQUAL(-100, A);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700245 ASSERT_EQUAL(1999, b);
Ed Tanous1ff48782017-04-18 12:45:08 -0700246 }
247 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700248 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700249 Request req{r};
250 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700251
252 req.url = "/4/5000/3/-2.71828/hellhere";
Ed Tanous1ff48782017-04-18 12:45:08 -0700253
254 app.handle(req, res);
255
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700256 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700257
258 ASSERT_EQUAL(5000, A);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700259 ASSERT_EQUAL(3, b);
Ed Tanous1ff48782017-04-18 12:45:08 -0700260 ASSERT_EQUAL(-2.71828, C);
261 ASSERT_EQUAL("hellhere", D);
262 }
263 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700264 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700265 Request req{r};
266 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700267
268 req.url = "/5/-5/999/3.141592/hello_there/a/b/c/d";
Ed Tanous1ff48782017-04-18 12:45:08 -0700269
270 app.handle(req, res);
271
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700272 ASSERT_EQUAL(200, res.resultInt());
Ed Tanous1ff48782017-04-18 12:45:08 -0700273
274 ASSERT_EQUAL(-5, A);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700275 ASSERT_EQUAL(999, b);
Ed Tanous1ff48782017-04-18 12:45:08 -0700276 ASSERT_EQUAL(3.141592, C);
277 ASSERT_EQUAL("hello_there", D);
278 ASSERT_EQUAL("a/b/c/d", E);
279 }
Ed Tanous8041f312017-04-03 09:47:01 -0700280}
281
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700282TEST(Crow, simple_response_RoutingParams) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700283 ASSERT_EQUAL(100,
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700284 Response(boost::beast::http::status::continue_).resultInt());
285 ASSERT_EQUAL(200, Response("Hello there").resultInt());
286 ASSERT_EQUAL(500, Response(boost::beast::http::status::internal_server_error,
Ed Tanouse0d918b2018-03-27 17:41:04 -0700287 "Internal Error?")
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700288 .resultInt());
Ed Tanous8041f312017-04-03 09:47:01 -0700289
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700290 RoutingParams rp;
291 rp.intParams.push_back(1);
292 rp.intParams.push_back(5);
293 rp.uintParams.push_back(2);
294 rp.doubleParams.push_back(3);
295 rp.stringParams.push_back("hello");
Ed Tanous1ff48782017-04-18 12:45:08 -0700296 ASSERT_EQUAL(1, rp.get<int64_t>(0));
297 ASSERT_EQUAL(5, rp.get<int64_t>(1));
298 ASSERT_EQUAL(2, rp.get<uint64_t>(0));
299 ASSERT_EQUAL(3, rp.get<double>(0));
300 ASSERT_EQUAL("hello", rp.get<string>(0));
Ed Tanous8041f312017-04-03 09:47:01 -0700301}
302
Ed Tanous1ff48782017-04-18 12:45:08 -0700303TEST(Crow, handler_with_response) {
304 SimpleApp app;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700305 BMCWEB_ROUTE(app, "/")([](const crow::Request&, crow::Response&) {});
Ed Tanous8041f312017-04-03 09:47:01 -0700306}
307
Ed Tanous1ff48782017-04-18 12:45:08 -0700308TEST(Crow, http_method) {
309 SimpleApp app;
Ed Tanous8041f312017-04-03 09:47:01 -0700310
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700311 BMCWEB_ROUTE(app, "/").methods("POST"_method,
312 "GET"_method)([](const Request& req) {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700313 if (req.method() == "GET"_method)
Ed Tanous1ff48782017-04-18 12:45:08 -0700314 return "2";
315 else
316 return "1";
317 });
318
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700319 BMCWEB_ROUTE(app, "/get_only")
320 .methods("GET"_method)([](const Request& /*req*/) { return "get"; });
321 BMCWEB_ROUTE(app, "/post_only")
322 .methods("POST"_method)([](const Request& /*req*/) { return "post"; });
Ed Tanous1ff48782017-04-18 12:45:08 -0700323
324 // cannot have multiple handlers for the same url
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700325 // BMCWEB_ROUTE(app, "/")
Ed Tanous1ff48782017-04-18 12:45:08 -0700326 //.methods("GET"_method)
327 //([]{ return "2"; });
328
329 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700330 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700331 Request req{r};
332 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700333
334 req.url = "/";
335 app.handle(req, res);
336
Ed Tanouse0d918b2018-03-27 17:41:04 -0700337 ASSERT_EQUAL("2", res.body());
Ed Tanous1ff48782017-04-18 12:45:08 -0700338 }
339 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700340 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700341 Request req{r};
342 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700343
344 req.url = "/";
Ed Tanouse0d918b2018-03-27 17:41:04 -0700345 r.method("POST"_method);
Ed Tanous1ff48782017-04-18 12:45:08 -0700346 app.handle(req, res);
347
Ed Tanouse0d918b2018-03-27 17:41:04 -0700348 ASSERT_EQUAL("1", res.body());
Ed Tanous1ff48782017-04-18 12:45:08 -0700349 }
350
351 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700352 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700353 Request req{r};
354 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700355
356 req.url = "/get_only";
357 app.handle(req, res);
358
Ed Tanouse0d918b2018-03-27 17:41:04 -0700359 ASSERT_EQUAL("get", res.body());
Ed Tanous1ff48782017-04-18 12:45:08 -0700360 }
361
362 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700363 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700364 Request req{r};
365 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700366
367 req.url = "/get_only";
Ed Tanouse0d918b2018-03-27 17:41:04 -0700368 r.method("POST"_method);
Ed Tanous1ff48782017-04-18 12:45:08 -0700369 app.handle(req, res);
370
Ed Tanouse0d918b2018-03-27 17:41:04 -0700371 ASSERT_NOTEQUAL("get", res.body());
Ed Tanous1ff48782017-04-18 12:45:08 -0700372 }
Ed Tanous8041f312017-04-03 09:47:01 -0700373}
374
Ed Tanous1ff48782017-04-18 12:45:08 -0700375TEST(Crow, server_handling_error_request) {
376 static char buf[2048];
377 SimpleApp app;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700378 BMCWEB_ROUTE(app, "/")([] { return "A"; });
Ed Tanous1ff48782017-04-18 12:45:08 -0700379 Server<SimpleApp> server(&app, LOCALHOST_ADDRESS, 45451);
380 auto _ = async(launch::async, [&] { server.run(); });
381 std::string sendmsg = "POX";
382 asio::io_service is;
383 {
384 asio::ip::tcp::socket c(is);
385 c.connect(asio::ip::tcp::endpoint(
386 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
Ed Tanous8041f312017-04-03 09:47:01 -0700387
Ed Tanous1ff48782017-04-18 12:45:08 -0700388 c.send(asio::buffer(sendmsg));
Ed Tanous8041f312017-04-03 09:47:01 -0700389
Ed Tanous1ff48782017-04-18 12:45:08 -0700390 try {
391 c.receive(asio::buffer(buf, 2048));
392 fail();
393 } catch (std::exception& e) {
394 // std::cerr << e.what() << std::endl;
Ed Tanous8041f312017-04-03 09:47:01 -0700395 }
Ed Tanous1ff48782017-04-18 12:45:08 -0700396 }
397 server.stop();
398}
Ed Tanous8041f312017-04-03 09:47:01 -0700399
Ed Tanous1ff48782017-04-18 12:45:08 -0700400TEST(Crow, multi_server) {
401 static char buf[2048];
402 SimpleApp app1, app2;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700403 BMCWEB_ROUTE(app1, "/").methods("GET"_method,
404 "POST"_method)([] { return "A"; });
405 BMCWEB_ROUTE(app2, "/").methods("GET"_method,
406 "POST"_method)([] { return "B"; });
Ed Tanous8041f312017-04-03 09:47:01 -0700407
Ed Tanous1ff48782017-04-18 12:45:08 -0700408 Server<SimpleApp> server1(&app1, LOCALHOST_ADDRESS, 45451);
409 Server<SimpleApp> server2(&app2, LOCALHOST_ADDRESS, 45452);
410
411 auto _ = async(launch::async, [&] { server1.run(); });
412 auto _2 = async(launch::async, [&] { server2.run(); });
413
414 std::string sendmsg =
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700415 "POST /\r\nContent-Length:3\r\nX-HeaderTest: 123\r\n\r\nA=b\r\n";
Ed Tanous1ff48782017-04-18 12:45:08 -0700416 asio::io_service is;
417 {
418 asio::ip::tcp::socket c(is);
419 c.connect(asio::ip::tcp::endpoint(
420 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
421
422 c.send(asio::buffer(sendmsg));
423
424 size_t recved = c.receive(asio::buffer(buf, 2048));
425 ASSERT_EQUAL('A', buf[recved - 1]);
426 }
427
428 {
429 asio::ip::tcp::socket c(is);
430 c.connect(asio::ip::tcp::endpoint(
431 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45452));
432
433 for (auto ch : sendmsg) {
434 char buf[1] = {ch};
435 c.send(asio::buffer(buf));
Ed Tanous8041f312017-04-03 09:47:01 -0700436 }
437
Ed Tanous1ff48782017-04-18 12:45:08 -0700438 size_t recved = c.receive(asio::buffer(buf, 2048));
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700439 ASSERT_EQUAL('b', buf[recved - 1]);
Ed Tanous1ff48782017-04-18 12:45:08 -0700440 }
Ed Tanous8041f312017-04-03 09:47:01 -0700441
Ed Tanous1ff48782017-04-18 12:45:08 -0700442 server1.stop();
443 server2.stop();
444}
Ed Tanous8041f312017-04-03 09:47:01 -0700445
Ed Tanous1ff48782017-04-18 12:45:08 -0700446TEST(Crow, black_magic) {
447 using namespace black_magic;
448 static_assert(
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700449 std::is_same<void, LastElementType<int, char, void>::type>::value,
450 "LastElementType");
Ed Tanous1ff48782017-04-18 12:45:08 -0700451 static_assert(
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700452 std::is_same<
453 char, PopBack<int, char, void>::rebind<LastElementType>::type>::value,
454 "pop_back");
455 static_assert(
456 std::is_same<int, PopBack<int, char, void>::rebind<PopBack>::rebind<
457 LastElementType>::type>::value,
Ed Tanous1ff48782017-04-18 12:45:08 -0700458 "pop_back");
Ed Tanous8041f312017-04-03 09:47:01 -0700459}
460
Ed Tanous1ff48782017-04-18 12:45:08 -0700461struct NullMiddleware {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700462 struct Context {};
Ed Tanous8041f312017-04-03 09:47:01 -0700463
Ed Tanous1ff48782017-04-18 12:45:08 -0700464 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700465 void beforeHandle(Request&, Response&, Context&, AllContext&) {}
Ed Tanous8041f312017-04-03 09:47:01 -0700466
Ed Tanous1ff48782017-04-18 12:45:08 -0700467 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700468 void afterHandle(Request&, Response&, Context&, AllContext&) {}
Ed Tanous8041f312017-04-03 09:47:01 -0700469};
470
Ed Tanous1ff48782017-04-18 12:45:08 -0700471struct NullSimpleMiddleware {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700472 struct Context {};
Ed Tanous8041f312017-04-03 09:47:01 -0700473
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700474 void beforeHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) {}
Ed Tanous8041f312017-04-03 09:47:01 -0700475
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700476 void afterHandle(Request& /*req*/, Response& /*res*/, Context& /*ctx*/) {}
Ed Tanous8041f312017-04-03 09:47:01 -0700477};
478
Ed Tanous1ff48782017-04-18 12:45:08 -0700479TEST(Crow, middleware_simple) {
480 App<NullMiddleware, NullSimpleMiddleware> app;
481 decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700482 BMCWEB_ROUTE(app, "/")
483 ([&](const crow::Request& req) {
484 app.getContext<NullMiddleware>(req);
485 app.getContext<NullSimpleMiddleware>(req);
Ed Tanous1ff48782017-04-18 12:45:08 -0700486 return "";
487 });
Ed Tanous8041f312017-04-03 09:47:01 -0700488}
489
Ed Tanous1ff48782017-04-18 12:45:08 -0700490struct IntSettingMiddleware {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700491 struct Context {
Ed Tanous1ff48782017-04-18 12:45:08 -0700492 int val;
493 };
Ed Tanous8041f312017-04-03 09:47:01 -0700494
Ed Tanous1ff48782017-04-18 12:45:08 -0700495 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700496 void beforeHandle(Request&, Response&, Context& ctx, AllContext&) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700497 ctx.val = 1;
498 }
Ed Tanous8041f312017-04-03 09:47:01 -0700499
Ed Tanous1ff48782017-04-18 12:45:08 -0700500 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700501 void afterHandle(Request&, Response&, Context& ctx, AllContext&) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700502 ctx.val = 2;
503 }
Ed Tanous8041f312017-04-03 09:47:01 -0700504};
505
506std::vector<std::string> test_middleware_context_vector;
507
Ed Tanous1ff48782017-04-18 12:45:08 -0700508struct FirstMW {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700509 struct Context {
Ed Tanous1ff48782017-04-18 12:45:08 -0700510 std::vector<string> v;
511 };
Ed Tanous8041f312017-04-03 09:47:01 -0700512
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700513 void beforeHandle(Request& /*req*/, Response& /*res*/, Context& ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700514 ctx.v.push_back("1 before");
515 }
Ed Tanous8041f312017-04-03 09:47:01 -0700516
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700517 void afterHandle(Request& /*req*/, Response& /*res*/, Context& ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700518 ctx.v.push_back("1 after");
519 test_middleware_context_vector = ctx.v;
520 }
Ed Tanous8041f312017-04-03 09:47:01 -0700521};
522
Ed Tanous1ff48782017-04-18 12:45:08 -0700523struct SecondMW {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700524 struct Context {};
Ed Tanous1ff48782017-04-18 12:45:08 -0700525 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700526 void beforeHandle(Request& req, Response& res, Context&,
527 AllContext& all_ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700528 all_ctx.template get<FirstMW>().v.push_back("2 before");
529 if (req.url == "/break") res.end();
530 }
Ed Tanous8041f312017-04-03 09:47:01 -0700531
Ed Tanous1ff48782017-04-18 12:45:08 -0700532 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700533 void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700534 all_ctx.template get<FirstMW>().v.push_back("2 after");
535 }
Ed Tanous8041f312017-04-03 09:47:01 -0700536};
537
Ed Tanous1ff48782017-04-18 12:45:08 -0700538struct ThirdMW {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700539 struct Context {};
Ed Tanous1ff48782017-04-18 12:45:08 -0700540 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700541 void beforeHandle(Request&, Response&, Context&, AllContext& all_ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700542 all_ctx.template get<FirstMW>().v.push_back("3 before");
543 }
Ed Tanous8041f312017-04-03 09:47:01 -0700544
Ed Tanous1ff48782017-04-18 12:45:08 -0700545 template <typename AllContext>
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700546 void afterHandle(Request&, Response&, Context&, AllContext& all_ctx) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700547 all_ctx.template get<FirstMW>().v.push_back("3 after");
548 }
Ed Tanous8041f312017-04-03 09:47:01 -0700549};
550
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700551TEST(Crow, middlewareContext) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700552 static char buf[2048];
553 // SecondMW depends on FirstMW (it uses all_ctx.get<FirstMW>)
554 // so it leads to compile error if we remove FirstMW from definition
555 // App<IntSettingMiddleware, SecondMW> app;
556 // or change the order of FirstMW and SecondMW
557 // App<IntSettingMiddleware, SecondMW, FirstMW> app;
Ed Tanous8041f312017-04-03 09:47:01 -0700558
Ed Tanous1ff48782017-04-18 12:45:08 -0700559 App<IntSettingMiddleware, FirstMW, SecondMW, ThirdMW> app;
Ed Tanous8041f312017-04-03 09:47:01 -0700560
Ed Tanous1ff48782017-04-18 12:45:08 -0700561 int x{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700562 BMCWEB_ROUTE(app, "/")
563 ([&](const Request& req) {
Ed Tanous8041f312017-04-03 09:47:01 -0700564 {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700565 auto& ctx = app.getContext<IntSettingMiddleware>(req);
Ed Tanous1ff48782017-04-18 12:45:08 -0700566 x = ctx.val;
Ed Tanous8041f312017-04-03 09:47:01 -0700567 }
568 {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700569 auto& ctx = app.getContext<FirstMW>(req);
Ed Tanous1ff48782017-04-18 12:45:08 -0700570 ctx.v.push_back("handle");
Ed Tanous8041f312017-04-03 09:47:01 -0700571 }
Ed Tanous8041f312017-04-03 09:47:01 -0700572
Ed Tanous1ff48782017-04-18 12:45:08 -0700573 return "";
574 });
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700575 BMCWEB_ROUTE(app, "/break")
576 ([&](const Request& req) {
Ed Tanous8041f312017-04-03 09:47:01 -0700577 {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700578 auto& ctx = app.getContext<FirstMW>(req);
Ed Tanous1ff48782017-04-18 12:45:08 -0700579 ctx.v.push_back("handle");
Ed Tanous8041f312017-04-03 09:47:01 -0700580 }
Ed Tanous1ff48782017-04-18 12:45:08 -0700581
582 return "";
583 });
584
585 decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451);
586 auto _ = async(launch::async, [&] { server.run(); });
587 std::string sendmsg = "GET /\r\n\r\n";
588 asio::io_service is;
589 {
590 asio::ip::tcp::socket c(is);
591 c.connect(asio::ip::tcp::endpoint(
592 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
593
594 c.send(asio::buffer(sendmsg));
595
596 c.receive(asio::buffer(buf, 2048));
597 c.close();
598 }
599 {
600 auto& out = test_middleware_context_vector;
601 ASSERT_EQUAL(1, x);
602 ASSERT_EQUAL(7, out.size());
603 ASSERT_EQUAL("1 before", out[0]);
604 ASSERT_EQUAL("2 before", out[1]);
605 ASSERT_EQUAL("3 before", out[2]);
606 ASSERT_EQUAL("handle", out[3]);
607 ASSERT_EQUAL("3 after", out[4]);
608 ASSERT_EQUAL("2 after", out[5]);
609 ASSERT_EQUAL("1 after", out[6]);
610 }
611 std::string sendmsg2 = "GET /break\r\n\r\n";
612 {
613 asio::ip::tcp::socket c(is);
614 c.connect(asio::ip::tcp::endpoint(
615 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
616
617 c.send(asio::buffer(sendmsg2));
618
619 c.receive(asio::buffer(buf, 2048));
620 c.close();
621 }
622 {
623 auto& out = test_middleware_context_vector;
624 ASSERT_EQUAL(4, out.size());
625 ASSERT_EQUAL("1 before", out[0]);
626 ASSERT_EQUAL("2 before", out[1]);
627 ASSERT_EQUAL("2 after", out[2]);
628 ASSERT_EQUAL("1 after", out[3]);
629 }
630 server.stop();
Ed Tanous8041f312017-04-03 09:47:01 -0700631}
632
Ed Tanous1ff48782017-04-18 12:45:08 -0700633TEST(Crow, bug_quick_repeated_request) {
634 static char buf[2048];
635
636 SimpleApp app;
637
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700638 BMCWEB_ROUTE(app, "/")([&] { return "hello"; });
Ed Tanous1ff48782017-04-18 12:45:08 -0700639
640 decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451);
641 auto _ = async(launch::async, [&] { server.run(); });
642 std::string sendmsg = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n";
643 asio::io_service is;
644 {
645 std::vector<std::future<void>> v;
646 for (int i = 0; i < 5; i++) {
647 v.push_back(async(launch::async, [&] {
648 asio::ip::tcp::socket c(is);
649 c.connect(asio::ip::tcp::endpoint(
650 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
651
652 for (int j = 0; j < 5; j++) {
653 c.send(asio::buffer(sendmsg));
654
655 size_t received = c.receive(asio::buffer(buf, 2048));
656 ASSERT_EQUAL("hello",
657 std::string(buf + received - 5, buf + received));
Ed Tanous8041f312017-04-03 09:47:01 -0700658 }
Ed Tanous8041f312017-04-03 09:47:01 -0700659 c.close();
Ed Tanous1ff48782017-04-18 12:45:08 -0700660 }));
Ed Tanous8041f312017-04-03 09:47:01 -0700661 }
Ed Tanous1ff48782017-04-18 12:45:08 -0700662 }
663 server.stop();
Ed Tanous8041f312017-04-03 09:47:01 -0700664}
665
Ed Tanous1ff48782017-04-18 12:45:08 -0700666TEST(Crow, simple_url_params) {
667 static char buf[2048];
Ed Tanous8041f312017-04-03 09:47:01 -0700668
Ed Tanous1ff48782017-04-18 12:45:08 -0700669 SimpleApp app;
Ed Tanous8041f312017-04-03 09:47:01 -0700670
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700671 QueryString lastUrlParams;
Ed Tanous8041f312017-04-03 09:47:01 -0700672
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700673 BMCWEB_ROUTE(app, "/params")
674 ([&lastUrlParams](const crow::Request& req) {
675 lastUrlParams = std::move(req.urlParams);
Ed Tanous1ff48782017-04-18 12:45:08 -0700676 return "OK";
677 });
Ed Tanous8041f312017-04-03 09:47:01 -0700678
Ed Tanous1ff48782017-04-18 12:45:08 -0700679 /// params?h=1&foo=bar&lol&count[]=1&count[]=4&pew=5.2
Ed Tanous8041f312017-04-03 09:47:01 -0700680
Ed Tanous1ff48782017-04-18 12:45:08 -0700681 decltype(app)::server_t server(&app, LOCALHOST_ADDRESS, 45451);
682 auto _ = async(launch::async, [&] { server.run(); });
683 asio::io_service is;
684 std::string sendmsg;
685
686 // check empty params
687 sendmsg = "GET /params\r\n\r\n";
688 {
689 asio::ip::tcp::socket c(is);
690 c.connect(asio::ip::tcp::endpoint(
691 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
692 c.send(asio::buffer(sendmsg));
693 c.receive(asio::buffer(buf, 2048));
694 c.close();
695
696 stringstream ss;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700697 ss << lastUrlParams;
Ed Tanous1ff48782017-04-18 12:45:08 -0700698
699 ASSERT_EQUAL("[ ]", ss.str());
700 }
701 // check single presence
702 sendmsg = "GET /params?foobar\r\n\r\n";
703 {
704 asio::ip::tcp::socket c(is);
705 c.connect(asio::ip::tcp::endpoint(
706 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
707 c.send(asio::buffer(sendmsg));
708 c.receive(asio::buffer(buf, 2048));
709 c.close();
710
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700711 ASSERT_TRUE(lastUrlParams.get("missing") == nullptr);
712 ASSERT_TRUE(lastUrlParams.get("foobar") != nullptr);
713 ASSERT_TRUE(lastUrlParams.getList("missing").empty());
Ed Tanous1ff48782017-04-18 12:45:08 -0700714 }
715 // check multiple presence
716 sendmsg = "GET /params?foo&bar&baz\r\n\r\n";
717 {
718 asio::ip::tcp::socket c(is);
719 c.connect(asio::ip::tcp::endpoint(
720 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
721 c.send(asio::buffer(sendmsg));
722 c.receive(asio::buffer(buf, 2048));
723 c.close();
724
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700725 ASSERT_TRUE(lastUrlParams.get("missing") == nullptr);
726 ASSERT_TRUE(lastUrlParams.get("foo") != nullptr);
727 ASSERT_TRUE(lastUrlParams.get("bar") != nullptr);
728 ASSERT_TRUE(lastUrlParams.get("baz") != nullptr);
Ed Tanous1ff48782017-04-18 12:45:08 -0700729 }
730 // check single value
731 sendmsg = "GET /params?hello=world\r\n\r\n";
732 {
733 asio::ip::tcp::socket c(is);
734 c.connect(asio::ip::tcp::endpoint(
735 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
736 c.send(asio::buffer(sendmsg));
737 c.receive(asio::buffer(buf, 2048));
738 c.close();
739
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700740 ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world");
Ed Tanous1ff48782017-04-18 12:45:08 -0700741 }
742 // check multiple value
743 sendmsg = "GET /params?hello=world&left=right&up=down\r\n\r\n";
744 {
745 asio::ip::tcp::socket c(is);
746 c.connect(asio::ip::tcp::endpoint(
747 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
748 c.send(asio::buffer(sendmsg));
749 c.receive(asio::buffer(buf, 2048));
750 c.close();
751
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700752 ASSERT_EQUAL(string(lastUrlParams.get("hello")), "world");
753 ASSERT_EQUAL(string(lastUrlParams.get("left")), "right");
754 ASSERT_EQUAL(string(lastUrlParams.get("up")), "down");
Ed Tanous1ff48782017-04-18 12:45:08 -0700755 }
756 // check multiple value, multiple types
757 sendmsg = "GET /params?int=100&double=123.45&boolean=1\r\n\r\n";
758 {
759 asio::ip::tcp::socket c(is);
760 c.connect(asio::ip::tcp::endpoint(
761 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
762 c.send(asio::buffer(sendmsg));
763 c.receive(asio::buffer(buf, 2048));
764 c.close();
765
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700766 ASSERT_EQUAL(boost::lexical_cast<int>(lastUrlParams.get("int")), 100);
767 ASSERT_EQUAL(boost::lexical_cast<double>(lastUrlParams.get("double")),
Ed Tanous1ff48782017-04-18 12:45:08 -0700768 123.45);
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700769 ASSERT_EQUAL(boost::lexical_cast<bool>(lastUrlParams.get("boolean")), true);
Ed Tanous1ff48782017-04-18 12:45:08 -0700770 }
771 // check single array value
772 sendmsg = "GET /params?tmnt[]=leonardo\r\n\r\n";
773 {
774 asio::ip::tcp::socket c(is);
775
776 c.connect(asio::ip::tcp::endpoint(
777 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
778 c.send(asio::buffer(sendmsg));
779 c.receive(asio::buffer(buf, 2048));
780 c.close();
781
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700782 ASSERT_TRUE(lastUrlParams.get("tmnt") == nullptr);
783 ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 1);
784 ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo");
Ed Tanous1ff48782017-04-18 12:45:08 -0700785 }
786 // check multiple array value
787 sendmsg =
788 "GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael\r\n\r\n";
789 {
790 asio::ip::tcp::socket c(is);
791
792 c.connect(asio::ip::tcp::endpoint(
793 asio::ip::address::from_string(LOCALHOST_ADDRESS), 45451));
794 c.send(asio::buffer(sendmsg));
795 c.receive(asio::buffer(buf, 2048));
796 c.close();
797
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700798 ASSERT_EQUAL(lastUrlParams.getList("tmnt").size(), 3);
799 ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[0]), "leonardo");
800 ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[1]), "donatello");
801 ASSERT_EQUAL(string(lastUrlParams.getList("tmnt")[2]), "raphael");
Ed Tanous1ff48782017-04-18 12:45:08 -0700802 }
803 server.stop();
Ed Tanous8041f312017-04-03 09:47:01 -0700804}
805
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700806TEST(Crow, routeDynamic) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700807 SimpleApp app;
808 int x = 1;
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700809 app.routeDynamic("/")([&] {
Ed Tanous1ff48782017-04-18 12:45:08 -0700810 x = 2;
811 return "";
812 });
Ed Tanous8041f312017-04-03 09:47:01 -0700813
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700814 app.routeDynamic("/set4")([&](const Request&) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700815 x = 4;
816 return "";
817 });
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700818 app.routeDynamic("/set5")([&](const Request&, Response& res) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700819 x = 5;
820 res.end();
821 });
Ed Tanous8041f312017-04-03 09:47:01 -0700822
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700823 app.routeDynamic("/set_int/<int>")([&](int y) {
Ed Tanous1ff48782017-04-18 12:45:08 -0700824 x = y;
825 return "";
826 });
Ed Tanous8041f312017-04-03 09:47:01 -0700827
Ed Tanous1ff48782017-04-18 12:45:08 -0700828 try {
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700829 app.routeDynamic("/invalid_test/<double>/<path>")([]() { return ""; });
Ed Tanous1ff48782017-04-18 12:45:08 -0700830 fail();
831 } catch (std::exception&) {
832 }
Ed Tanous8041f312017-04-03 09:47:01 -0700833
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700834 // app is in an invalid state when routeDynamic throws an exception.
Ed Tanous1ff48782017-04-18 12:45:08 -0700835 try {
836 app.validate();
837 fail();
838 } catch (std::exception&) {
839 }
Ed Tanous8041f312017-04-03 09:47:01 -0700840
Ed Tanous1ff48782017-04-18 12:45:08 -0700841 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700842 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700843 Request req{r};
844 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700845 req.url = "/";
846 app.handle(req, res);
847 ASSERT_EQUAL(x, 2);
848 }
849 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700850 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700851 Request req{r};
852 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700853 req.url = "/set_int/42";
854 app.handle(req, res);
855 ASSERT_EQUAL(x, 42);
856 }
857 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700858 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700859 Request req{r};
860 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700861 req.url = "/set5";
862 app.handle(req, res);
863 ASSERT_EQUAL(x, 5);
864 }
865 {
Ed Tanouse0d918b2018-03-27 17:41:04 -0700866 boost::beast::http::request<boost::beast::http::string_body> r{};
Ed Tanous55c7b7a2018-05-22 15:27:24 -0700867 Request req{r};
868 Response res;
Ed Tanous1ff48782017-04-18 12:45:08 -0700869 req.url = "/set4";
870 app.handle(req, res);
871 ASSERT_EQUAL(x, 4);
872 }
Ed Tanous8041f312017-04-03 09:47:01 -0700873}