test.cc 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. #include <gtest/gtest.h>
  2. #include <httplib.h>
  3. #include <future>
  4. #include <iostream>
  5. #define SERVER_CERT_FILE "./cert.pem"
  6. #define SERVER_PRIVATE_KEY_FILE "./key.pem"
  7. #ifdef _WIN32
  8. #include <process.h>
  9. #define msleep(n) ::Sleep(n)
  10. #else
  11. #define msleep(n) ::usleep(n * 1000)
  12. #endif
  13. using namespace std;
  14. using namespace httplib;
  15. const char* HOST = "localhost";
  16. const int PORT = 1234;
  17. #ifdef _WIN32
  18. TEST(StartupTest, WSAStartup)
  19. {
  20. WSADATA wsaData;
  21. int ret = WSAStartup(0x0002, &wsaData);
  22. ASSERT_EQ(0, ret);
  23. }
  24. #endif
  25. TEST(SplitTest, ParseQueryString)
  26. {
  27. string s = "key1=val1&key2=val2&key3=val3";
  28. map<string, string> dic;
  29. detail::split(s.c_str(), s.c_str() + s.size(), '&', [&](const char* b, const char* e) {
  30. string key, val;
  31. detail::split(b, e, '=', [&](const char* b, const char* e) {
  32. if (key.empty()) {
  33. key.assign(b, e);
  34. } else {
  35. val.assign(b, e);
  36. }
  37. });
  38. dic[key] = val;
  39. });
  40. EXPECT_EQ("val1", dic["key1"]);
  41. EXPECT_EQ("val2", dic["key2"]);
  42. EXPECT_EQ("val3", dic["key3"]);
  43. }
  44. TEST(ParseQueryTest, ParseQueryString)
  45. {
  46. string s = "key1=val1&key2=val2&key3=val3";
  47. map<string, string> dic;
  48. detail::parse_query_text(s, dic);
  49. EXPECT_EQ("val1", dic["key1"]);
  50. EXPECT_EQ("val2", dic["key2"]);
  51. EXPECT_EQ("val3", dic["key3"]);
  52. }
  53. TEST(SocketTest, OpenClose)
  54. {
  55. socket_t sock = detail::create_server_socket(HOST, PORT, 0);
  56. ASSERT_NE(-1, sock);
  57. auto ret = detail::close_socket(sock);
  58. EXPECT_EQ(0, ret);
  59. }
  60. TEST(SocketTest, OpenCloseWithAI_PASSIVE)
  61. {
  62. socket_t sock = detail::create_server_socket(nullptr, PORT, AI_PASSIVE);
  63. ASSERT_NE(-1, sock);
  64. auto ret = detail::close_socket(sock);
  65. EXPECT_EQ(0, ret);
  66. }
  67. TEST(GetHeaderValueTest, DefaultValue)
  68. {
  69. MultiMap map = {{"Dummy","Dummy"}};
  70. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  71. ASSERT_STREQ("text/plain", val);
  72. }
  73. TEST(GetHeaderValueTest, DefaultValueInt)
  74. {
  75. MultiMap map = {{"Dummy","Dummy"}};
  76. auto val = detail::get_header_value_int(map, "Content-Length", 100);
  77. EXPECT_EQ(100, val);
  78. }
  79. TEST(GetHeaderValueTest, RegularValue)
  80. {
  81. MultiMap map = {{"Content-Type", "text/html"}, {"Dummy", "Dummy"}};
  82. auto val = detail::get_header_value(map, "Content-Type", "text/plain");
  83. ASSERT_STREQ("text/html", val);
  84. }
  85. TEST(GetHeaderValueTest, RegularValueInt)
  86. {
  87. MultiMap map = {{"Content-Length", "100"}, {"Dummy", "Dummy"}};
  88. auto val = detail::get_header_value_int(map, "Content-Length", 0);
  89. EXPECT_EQ(100, val);
  90. }
  91. class ServerTest : public ::testing::Test {
  92. protected:
  93. ServerTest()
  94. : cli_(HOST, PORT)
  95. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  96. , svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  97. #endif
  98. , up_(false) {}
  99. virtual void SetUp() {
  100. svr_.set_base_dir("./www");
  101. svr_.get("/hi", [&](const Request& /*req*/, Response& res) {
  102. res.set_content("Hello World!", "text/plain");
  103. })
  104. .get("/", [&](const Request& /*req*/, Response& res) {
  105. res.set_redirect("/hi");
  106. })
  107. .post("/person", [&](const Request& req, Response& res) {
  108. if (req.has_param("name") && req.has_param("note")) {
  109. persons_[req.params.at("name")] = req.params.at("note");
  110. } else {
  111. res.status = 400;
  112. }
  113. })
  114. .get("/person/(.*)", [&](const Request& req, Response& res) {
  115. string name = req.matches[1];
  116. if (persons_.find(name) != persons_.end()) {
  117. auto note = persons_[name];
  118. res.set_content(note, "text/plain");
  119. } else {
  120. res.status = 404;
  121. }
  122. })
  123. .get("/stop", [&](const Request& /*req*/, Response& /*res*/) {
  124. svr_.stop();
  125. });
  126. persons_["john"] = "programmer";
  127. f_ = async([&](){
  128. up_ = true;
  129. svr_.listen(HOST, PORT);
  130. });
  131. while (!up_) {
  132. msleep(1);
  133. }
  134. }
  135. virtual void TearDown() {
  136. //svr_.stop(); // NOTE: This causes dead lock on Windows.
  137. cli_.get("/stop");
  138. f_.get();
  139. }
  140. map<string, string> persons_;
  141. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  142. SSLClient cli_;
  143. SSLServer svr_;
  144. #else
  145. Client cli_;
  146. Server svr_;
  147. #endif
  148. future<void> f_;
  149. bool up_;
  150. };
  151. TEST_F(ServerTest, GetMethod200)
  152. {
  153. auto res = cli_.get("/hi");
  154. ASSERT_TRUE(res != nullptr);
  155. EXPECT_EQ(200, res->status);
  156. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  157. EXPECT_EQ("Hello World!", res->body);
  158. }
  159. TEST_F(ServerTest, GetMethod302)
  160. {
  161. auto res = cli_.get("/");
  162. ASSERT_TRUE(res != nullptr);
  163. EXPECT_EQ(302, res->status);
  164. EXPECT_EQ("/hi", res->get_header_value("Location"));
  165. }
  166. TEST_F(ServerTest, GetMethod404)
  167. {
  168. auto res = cli_.get("/invalid");
  169. ASSERT_TRUE(res != nullptr);
  170. EXPECT_EQ(404, res->status);
  171. }
  172. TEST_F(ServerTest, HeadMethod200)
  173. {
  174. auto res = cli_.head("/hi");
  175. ASSERT_TRUE(res != nullptr);
  176. EXPECT_EQ(200, res->status);
  177. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  178. EXPECT_EQ("", res->body);
  179. }
  180. TEST_F(ServerTest, HeadMethod404)
  181. {
  182. auto res = cli_.head("/invalid");
  183. ASSERT_TRUE(res != nullptr);
  184. EXPECT_EQ(404, res->status);
  185. EXPECT_EQ("", res->body);
  186. }
  187. TEST_F(ServerTest, GetMethodPersonJohn)
  188. {
  189. auto res = cli_.get("/person/john");
  190. ASSERT_TRUE(res != nullptr);
  191. EXPECT_EQ(200, res->status);
  192. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  193. EXPECT_EQ("programmer", res->body);
  194. }
  195. TEST_F(ServerTest, PostMethod1)
  196. {
  197. auto res = cli_.get("/person/john1");
  198. ASSERT_TRUE(res != nullptr);
  199. ASSERT_EQ(404, res->status);
  200. res = cli_.post("/person", "name=john1&note=coder", "application/x-www-form-urlencoded");
  201. ASSERT_TRUE(res != nullptr);
  202. ASSERT_EQ(200, res->status);
  203. res = cli_.get("/person/john1");
  204. ASSERT_TRUE(res != nullptr);
  205. ASSERT_EQ(200, res->status);
  206. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  207. ASSERT_EQ("coder", res->body);
  208. }
  209. TEST_F(ServerTest, PostMethod2)
  210. {
  211. auto res = cli_.get("/person/john2");
  212. ASSERT_TRUE(res != nullptr);
  213. ASSERT_EQ(404, res->status);
  214. Map params;
  215. params["name"] = "john2";
  216. params["note"] = "coder";
  217. res = cli_.post("/person", params);
  218. ASSERT_TRUE(res != nullptr);
  219. ASSERT_EQ(200, res->status);
  220. res = cli_.get("/person/john2");
  221. ASSERT_TRUE(res != nullptr);
  222. ASSERT_EQ(200, res->status);
  223. ASSERT_EQ("text/plain", res->get_header_value("Content-Type"));
  224. ASSERT_EQ("coder", res->body);
  225. }
  226. TEST_F(ServerTest, GetMethodDir)
  227. {
  228. auto res = cli_.get("/dir/");
  229. ASSERT_TRUE(res != nullptr);
  230. EXPECT_EQ(200, res->status);
  231. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  232. auto body = R"(<html>
  233. <head>
  234. </head>
  235. <body>
  236. <a href="/dir/test.html">Test</a>
  237. <a href="/hi">hi</a>
  238. </body>
  239. </html>
  240. )";
  241. EXPECT_EQ(body, res->body);
  242. }
  243. TEST_F(ServerTest, GetMethodDirTest)
  244. {
  245. auto res = cli_.get("/dir/test.html");
  246. ASSERT_TRUE(res != nullptr);
  247. EXPECT_EQ(200, res->status);
  248. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  249. EXPECT_EQ("test.html", res->body);
  250. }
  251. TEST_F(ServerTest, GetMethodDirTestWithDoubleDots)
  252. {
  253. auto res = cli_.get("/dir/../dir/test.html");
  254. ASSERT_TRUE(res != nullptr);
  255. EXPECT_EQ(200, res->status);
  256. EXPECT_EQ("text/html", res->get_header_value("Content-Type"));
  257. EXPECT_EQ("test.html", res->body);
  258. }
  259. TEST_F(ServerTest, GetMethodInvalidPath)
  260. {
  261. auto res = cli_.get("/dir/../test.html");
  262. ASSERT_TRUE(res != nullptr);
  263. EXPECT_EQ(404, res->status);
  264. }
  265. TEST_F(ServerTest, GetMethodOutOfBaseDir)
  266. {
  267. auto res = cli_.get("/../www/dir/test.html");
  268. ASSERT_TRUE(res != nullptr);
  269. EXPECT_EQ(404, res->status);
  270. }
  271. TEST_F(ServerTest, GetMethodOutOfBaseDir2)
  272. {
  273. auto res = cli_.get("/dir/../../www/dir/test.html");
  274. ASSERT_TRUE(res != nullptr);
  275. EXPECT_EQ(404, res->status);
  276. }
  277. TEST_F(ServerTest, InvalidBaseDir)
  278. {
  279. EXPECT_EQ(false, svr_.set_base_dir("invalid_dir"));
  280. EXPECT_EQ(true, svr_.set_base_dir("."));
  281. }
  282. TEST_F(ServerTest, EmptyRequest)
  283. {
  284. auto res = cli_.get("");
  285. ASSERT_TRUE(res != nullptr);
  286. EXPECT_EQ(400, res->status);
  287. }
  288. TEST_F(ServerTest, LongRequest)
  289. {
  290. auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ok__");
  291. ASSERT_TRUE(res != nullptr);
  292. EXPECT_EQ(404, res->status);
  293. }
  294. TEST_F(ServerTest, TooLongRequest)
  295. {
  296. auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ng___");
  297. ASSERT_TRUE(res != nullptr);
  298. EXPECT_EQ(400, res->status);
  299. }
  300. TEST_F(ServerTest, LongHeader)
  301. {
  302. Request req;
  303. req.method = "GET";
  304. req.path = "/hi";
  305. std::string host_and_port;
  306. host_and_port += HOST;
  307. host_and_port += ":";
  308. host_and_port += std::to_string(PORT);
  309. req.set_header("Host", host_and_port.c_str());
  310. req.set_header("Accept", "*/*");
  311. req.set_header("User-Agent", "cpp-httplib/0.1");
  312. req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  313. auto res = std::make_shared<Response>();
  314. auto ret = cli_.send(req, *res);
  315. ASSERT_TRUE(ret);
  316. EXPECT_EQ(200, res->status);
  317. }
  318. TEST_F(ServerTest, TooLongHeader)
  319. {
  320. Request req;
  321. req.method = "GET";
  322. req.path = "/hi";
  323. std::string host_and_port;
  324. host_and_port += HOST;
  325. host_and_port += ":";
  326. host_and_port += std::to_string(PORT);
  327. req.set_header("Host", host_and_port.c_str());
  328. req.set_header("Accept", "*/*");
  329. req.set_header("User-Agent", "cpp-httplib/0.1");
  330. req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
  331. auto res = std::make_shared<Response>();
  332. auto ret = cli_.send(req, *res);
  333. ASSERT_TRUE(ret);
  334. EXPECT_EQ(400, res->status);
  335. }
  336. class ServerTestWithAI_PASSIVE : public ::testing::Test {
  337. protected:
  338. ServerTestWithAI_PASSIVE()
  339. : cli_(HOST, PORT)
  340. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  341. , svr_(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE)
  342. #endif
  343. , up_(false) {}
  344. virtual void SetUp() {
  345. svr_.get("/hi", [&](const Request& /*req*/, Response& res) {
  346. res.set_content("Hello World!", "text/plain");
  347. });
  348. svr_.get("/stop", [&](const Request& /*req*/, Response& /*res*/) {
  349. svr_.stop();
  350. });
  351. f_ = async([&](){
  352. up_ = true;
  353. svr_.listen(nullptr, PORT, AI_PASSIVE);
  354. });
  355. while (!up_) {
  356. msleep(1);
  357. }
  358. }
  359. virtual void TearDown() {
  360. //svr_.stop(); // NOTE: This causes dead lock on Windows.
  361. cli_.get("/stop");
  362. f_.get();
  363. }
  364. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  365. SSLClient cli_;
  366. SSLServer svr_;
  367. #else
  368. Client cli_;
  369. Server svr_;
  370. #endif
  371. future<void> f_;
  372. bool up_;
  373. };
  374. TEST_F(ServerTestWithAI_PASSIVE, GetMethod200)
  375. {
  376. auto res = cli_.get("/hi");
  377. ASSERT_TRUE(res != nullptr);
  378. EXPECT_EQ(200, res->status);
  379. EXPECT_EQ("text/plain", res->get_header_value("Content-Type"));
  380. EXPECT_EQ("Hello World!", res->body);
  381. }
  382. #ifdef CPPHTTPLIB_OPENSSL_SUPPORT
  383. TEST(SSLClientTest, ServerNameIndication)
  384. {
  385. SSLClient cli("httpbin.org", 443);
  386. auto res = cli.get("/get");
  387. ASSERT_TRUE(res != nullptr);
  388. ASSERT_EQ(200, res->status);
  389. }
  390. #endif
  391. #ifdef _WIN32
  392. TEST(CleanupTest, WSACleanup)
  393. {
  394. int ret = WSACleanup();
  395. ASSERT_EQ(0, ret);
  396. }
  397. #endif
  398. // vim: et ts=4 sw=4 cin cino={1s ff=unix